WINLIB2B Close buttons don't work.

Discussions related to mouse, keyboard and Graphical User Interface
User avatar
hellomike
Posts: 54
Joined: Sat 09 Jun 2018, 09:47

WINLIB2B Close buttons don't work.

Post by hellomike » Wed 26 Jun 2019, 11:53

Hi,

Yes, I know this behavior is documented in the help but I can't understand why Richard decided to put this in the WINLIB2B library or actually why he didn't just update WINLIB2.
As far as I can see from other applications (including BB4W IDE!) pressing escape or clicking the dialog box close button closes the dialog box.

Obviously the advantage to use WINLIB2B over WINLIB2 is that it forwards also WM_HELP and WM_NOTIFY messages. And yes, that is what I want as I need a WM_NOTIFY when an item in a ListView selected.

Still I fail to see why Richard didn't just update the WINLIB2 library because the programmer has control to allow/disallow this by *SYS1.

Bottom line is that I want/need to receive WM_NOTIFY but also to have close buttons behave in a common way, i.e. as in WINLIB2.

Do I need to modify WINLIB2B library assembly code (and how) or is there is simpler solution?

Thanks

Mike

Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: WINLIB2B Close buttons don't work.

Post by Zaphod » Wed 26 Jun 2019, 16:39

The idea is to allow some processing to occur before the window closes so WINLIB2B enhances the options. It requires you to do a little more processing to detect the close button press but that is simple enough.
You will get an interrupt message of WM_COMMAND (@msg%=273) with a control ID of ID_CANCEL (@wparam%=2) so you will look for this in your interrupt handler and issue a QUIT or whatever else you wish to do with that input.
That is much simpler than messing with the library and customizing it.

Hope this helps.

Z

User avatar
hellomike
Posts: 54
Joined: Sat 09 Jun 2018, 09:47

Re: WINLIB2B Close buttons don't work.

Post by hellomike » Wed 26 Jun 2019, 18:11

Hi Zaphod,

Thanks for the fast reply!
Actually I discovered today that at least WM_COMMAND with ID_CANCEL is send so I thought I was saved and that I could simply add this in my interrupt handler PROCedure, which is.....

Code: Select all

      DEF PROCappSys(msg%, wpa%, lpa%)
      LOCAL nc%, id%

      nc%=wpa%>>16 : id%=wpa% AND &FFFF
      CASE msg% OF

        WHEN WM_COMMAND     
          REM Dialog buttons...
          CASE id% OF
            WHEN 190, 199   PROCappAddCol(id%)
            WHEN 290, 299   PROCappCDSet(id%)
            WHEN 390, 399   PROCappOperations(id%)
            ......................
            WHEN 9990       PROCdebug(id%, "")
          ENDCASE
          IF id%>469 IF id%<480             PROCappCDWidths(id%)
          IF id%>=10000                     PROCappCellDetails(20, id%)
          IF id%=710 IF nc%=EN_CHANGE       PROCappSearchAlbum(10)
          IF id%=720 IF nc%=LBN_SELCHANGE   PROCappSearchAlbum(30)

        WHEN WM_NOTIFY
          IF id%=400 IF nc%=LVN_ITEMCHANGED PROCappCDWidths(10)
      ENDCASE
      ENDPROC
As you can see all controls have their dedicated PROC, each handling all functionality for a specific Dialog box.
However when receiving ID_CANCEL (@wparam%=2), the program doesn't know which dedicated PROC to call, i.e. for dialog box to issue PROC_closedialog().

Hope the above makes sense.

Mike

Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: WINLIB2B Close buttons don't work.

Post by Zaphod » Wed 26 Jun 2019, 20:09

Well if you keep a list of the dialog handles then you could presumably use SYS "GetActiveWindow" to find which one it was.

Z

p_m21987
Posts: 143
Joined: Mon 02 Apr 2018, 21:51

Re: WINLIB2B Close buttons don't work.

Post by p_m21987 » Wed 26 Jun 2019, 23:02

hellomike wrote:
Wed 26 Jun 2019, 11:53
I know this behavior is documented in the help but I can't understand why Richard decided to put this in the WINLIB2B library
You could always have asked him! The reason for the change in the behaviour of the Close button and the Escape key in WINLIB2B is simply because the way they behave in WINLIB2 is wrong! It is never sensible for a dialogue box unconditionally to close when Close or Escape is pressed: the programmer should always have the opportunity to suppress that action if it is not appropriate in the circumstances (like ON CLOSE in the main output window). Richard wasn't able to fix this in WINLIB2 because it would have introduced an incompatibility, but WINLIB2B gave him the opportunity to do it correctly.

The proper way for Close and Escape to work, and how they work in WINLIB2B, is for them to generate a WM_COMMAND message with an ID of 2 (Cancel); that can be intercepted in the normal way and, assuming you want the dialogue box to be closed as a result, you can call PROC_closedialog() to achieve that. Indeed if you look at the code of DLGDEMO.BBC you'll see that this is exactly what happens (even though WINLIB2 is normally used, you can change it to WINLIB2B and it will behave in exactly the same way).
hellomike wrote:
Wed 26 Jun 2019, 18:11
However when receiving ID_CANCEL (@wparam%=2), the program doesn't know which dedicated PROC to call, i.e. for dialog box to issue PROC_closedialog().
The situation you describe there is extremely unusual, because it implies that there are two or more 'modeless' dialogue boxes open at the same time. In Windows dialogue boxes are almost always modal (in which case there is no ambiguity in respect of which is being closed); modeless dialogue boxes (such as the Find/Replace dialogue) are uncommon and having two or more open at the same time is a situation Richard has never encountered.

So if you really do have two modeless dialogue boxes Richard would be concerned that your user interface is exceptionally non-standard. If you can make the dialogue boxes modal, and hence more conventional, there cannot be any doubt about which is being closed. As a last resort, if you are convinced modeless dialogue boxes are appropriate, you can still distinguish which is being closed because the lParam value passed in the WM_COMMAND message will contain the handle of the Cancel button in the relevant box (even if Close or Escape was pressed).

User avatar
hellomike
Posts: 54
Joined: Sat 09 Jun 2018, 09:47

Re: WINLIB2B Close buttons don't work.

Post by hellomike » Thu 27 Jun 2019, 10:02

Thanks for thinking along.

I agree that my handling of modal vs modeless boxes is an ongoing issue. Most of them can or rather should be modal.
Because of a menu-choice I call a PROC that opens the correct dialog box, like:

Code: Select all

      CASE msg% OF
        WHEN WM_COMMAND
          REM Menu handling...
          CASE id% OF
            ............. 
            WHEN 25 PROCappSearchAlbum(0)
            .............
If some control is clicked on the open dialog box I know what to do because all controls have unique id's upon creation, like:

Code: Select all

          IF id%=710 IF nc%=EN_CHANGE       PROCappSearchAlbum(10)
          IF id%=720 IF nc%=LBN_SELCHANGE   PROCappSearchAlbum(30)
However if close button is clicked, ID_CANCEL isn't unique. Guess I could create a global variable OpenDlg% or something that I set after every call PROC_showdialog(dlg%) in the program and then do PROC_closedialog(OpenDlg%) when ID_CANCEL is received.

Kind of defies my approach of keeping all functionality from the same dialog box (each control on it) in a dedicated PROC.

Will give it more thought I guess.

Mike

p_m21987
Posts: 143
Joined: Mon 02 Apr 2018, 21:51

Re: WINLIB2B Close buttons don't work.

Post by p_m21987 » Thu 27 Jun 2019, 11:59

Hello,

Richard says:

-----
hellomike wrote:
Thu 27 Jun 2019, 10:02
If some control is clicked on the open dialog box I know what to do because all controls have unique id's upon creation
Windows is designed in such a way that controls need not have unique IDs, for example the 'built in' dialogue boxes commonly reuse the same ID. So although that's something you can do when you have control of the IDs, it's not a general solution (and as you've noted the IDs for OK and Cancel/Close are mandated).
hellomike wrote:
Thu 27 Jun 2019, 10:02
Kind of defies my approach of keeping all functionality from the same dialog box (each control on it) in a dedicated PROC.
You could still do that, but the 'dispatch' mechanism that determines which PROC is called would have to take account of something which identifies the dialogue box. You could for example dispatch on the *handle* of the originating control rather than its *ID* (i.e. use lParam rather than wParam) which is guaranteed to be unique. As I said, if you press Escape or Close it will appear to have originated from the Cancel button according to the handle value.

-----

Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: WINLIB2B Close buttons don't work.

Post by Zaphod » Thu 27 Jun 2019, 23:03

So far as I can see, when you click on the close box of a dialog the @lparam% that is returned by ON SYS is "0", so that suggestion does not appear to work. Incidentally nor does my earlier suggestion of finding the active window. That also returns a "0". It looks like the calling thread is not the right one for those calls to work, but then again I may be missing something obvious.

Code: Select all

      REM This does not work.

      INSTALL @lib$+"WINLIB2B"
      :
      dlg%=FN_newdialog("First",50,50,100,100,8,200)
      PROC_showdialog(dlg%)

      dlg1%=FN_newdialog("Second",250,50,100,100,8,200)
      PROC_showdialog(dlg1%)

      dlg2%=FN_newdialog("Third",450,50,100,100,8,200)
      PROC_showdialog(dlg2%)
      :
      DIM Q%(2)
      ON SYS Q%()=@msg%, @wparam% AND &FFFF, @lparam% : RETURN

      REM ========================== MAIN LOOP =============================

      REPEAT
        IF Q%(1) = 2 THEN
          CASE TRUE OF
            WHEN Q%(2)=!dlg%: PROC_closedialog(dlg%)
            WHEN Q%(2)=!dlg1%: PROC_closedialog(dlg1%)
            WHEN Q%(2)=!dlg2%: PROC_closedialog(dlg2%)
          ENDCASE
          PRINT Q%(0), Q%(1), Q%(2)
        ENDIF
        Q%()=0
        WAIT 10
      UNTIL FALSE

      END
Z

User avatar
hellomike
Posts: 54
Joined: Sat 09 Jun 2018, 09:47

Re: WINLIB2B Close buttons don't work.

Post by hellomike » Fri 28 Jun 2019, 08:05

p_m21987,

Please thank Richard for his reply. He always provides good information.
So I was thinking of getting the dialog handle when there is a ID_CANCEL and then give all dialog-PROCs a change to match the dlg and do their business.

Was about to test how to obtain the handle today but.... Zaphod beat me to it and saves me a lot of work.

Zaphod: Thanks. And you say also "GetActiveWindow" doesn't work, right?
Your elegant piece of code shows my problem exactly! Even IF it would work, I need a WHEN for every possible value of dlg%. It also implies that all handles should be in global variables. They aren't. All the dialog-PROCs have a PRIVATE dlg%.
Then again, giving each PROC a chance to match is far more elegant I would say. But....... handle can't be found!

Only 'solution' I can think of is add code to all PROCs to save dlg% in a global OpenDlg% to indicate which box is open and then upon receiving ID_CANCEL do a PROC_closedialog(OpenDlg%).

Regards,

Mike

Zaphod
Posts: 78
Joined: Sat 23 Jun 2018, 15:51

Re: WINLIB2B Close buttons don't work.

Post by Zaphod » Fri 28 Jun 2019, 15:16

Actually I do have a modified version of WINLIB2B that does what you want from about 4 or 5 years ago, so it might not be the latest version. If you are interested then send me a private message and I will email it to you. It is not an 'approved' solution, obviously, so I won't post it here.

Z

Post Reply