Author Topic: Using Dynamic Dialogs  (Read 701 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Hero Member
  • *****
  • Posts: 510
Re: Using Dynamic Dialogs
« Reply #15 on: January 19, 2018, 04:06:56 PM »
Thank you Charles, for your encouraging words. As I used dialog.bas of the Freebasic forum as a template I had indeed some scupels to change the order of the arguments and I understand there is a logic behind the arrangement of the sub. But after the new formation I think the syntax is more conforming to MS Resource-Definition statements. An exception is with predefined controls, as I always start with a string (and if only empty).

I enhanced "% review" a little bit. If CreateModal/ModelessDialog fails, an error will be printed and followed by a waitkey statement to close the console, otherwise the application will disappear without warning in some cases.

The structure of the attached zipped file is now:
DynDialogs
     |
   Examples
         |
       DlgFromRc
       ResWithExe

In DlgFromRc there are examples of controls which I simply copied to the app. With predefined controls some modifications were necessary. Especially the many controls in cumulus.rc convinced me that it would be advantageous to change the order of the parameters in sub control and the routines for predefined classes.

I am still in a testing phase and I am studying the LoadMenuIndirect function to see if it would make sense to use it.

In folder Examples\ResWithExe there is a sample to create an app with an application Icon and a Bitmap in the dialog linked as a resource to the exe file. Unfortunately there are 3/65 warnings: Avira, Bkav, Cylance. Avira is a problem. With 64 bit there is 1 warning: Cylance.

To achieve this linking the argument: resource-id (rid) in function control is used instead of caption. I think all the time if I could use an overloaded function:

sub CONTROL( string caption, word cid, string _class, dword style=0, short x,y,cx,cy, optional extStyle = 0 )
sub CONTROL( short         rid, word cid, string _class, dword style=0, short x,y,cx,cy, optional extStyle = 0 )

I am not sure if this would work properly or if there is another solution? Otherwise I will stay with the existing approach.

Roland

Arnold

  • Hero Member
  • *****
  • Posts: 510
Re: Using Dynamic Dialogs - Menus
« Reply #16 on: January 22, 2018, 08:09:35 AM »
Hi Charles,

this is cool! (perhaps). I gave up the idea to use LoadMenuIndirect and used instead CreateMenu, Appendmenu with a macro and some helper functions. I used this .rc file as an example:

Code: [Select]
1 MENU
BEGIN
  POPUP "&File"
  BEGIN
    POPUP "&New"
    BEGIN
      MENUITEM "&Empty file",1100
      POPUP "By template &file..."
      BEGIN
        MENUITEM "Template 1",1102,CHECKED
        MENUITEM "Template 2",1103
        MENUITEM "Template 3",1104
      END
      MENUITEM SEPARATOR
      MENUITEM "Empty &window",1105
    END
    MENUITEM "&Open...\tCtrl+O",1110
    MENUITEM "&Save\tCtrl+S",1111
    MENUITEM "Save &as...\tF12",1112
    MENUITEM SEPARATOR
    MENUITEM "E&xit\tAlt+F4",1180
  END
  POPUP "&Edit"
  BEGIN
    MENUITEM "U&ndo\tCtrl+Z",1200,GRAYED
    MENUITEM SEPARATOR
    MENUITEM "&Cut\tCtrl+X",1201,GRAYED
    MENUITEM "C&opy\tCtrl+C",1202,GRAYED
    MENUITEM "&Paste\tCtrl+V",1203
    MENUITEM SEPARATOR
    MENUITEM "Select &all\tCtrl+A",1204
  END
  MENUITEM "&Compile!",1301
  MENUITEM "&Run!",1302
  POPUP "&Tools"
  BEGIN
    MENUITEM "&Compile\tF5",1301
    MENUITEM "&Run\tF6",1302
    MENUITEM SEPARATOR
    MENUITEM "&Edit Resources\tF7",1311
    MENUITEM SEPARATOR
    MENUITEM "Code &formatter...",1321
  END
  POPUP "&Options"
  BEGIN
    MENUITEM "&Font settings...",1401
    MENUITEM "&General settings...",1402
    MENUITEM "&Project settings...",1403
    MENUITEM SEPARATOR
    MENUITEM "Auto &indent",1411
  END
  POPUP "&Help"
  BEGIN
    MENUITEM "Help &keyword...\tF1",1900
    MENUITEM "&Basic help\tShift+F1",1901
    MENUITEM "&API help\tAlt+F1",1902
    MENUITEM "&Editor help\tCtrl+F1",1903
    MENUITEM SEPARATOR
    MENUITEM "Ab&out",1909
  END
END

After replacing (using dyn):
MENU with:
sys hMenu
MENU(hMenu)

 \t with: " tab "
SEPARATOR with "SEPARATOR"
END with ENDMenu

I will get this result:

Code: [Select]
'1 MENU
sys hMenu
dyn::MENU(hMenu)

dyn::BEGIN
  dyn::POPUP "&File"
  dyn::BEGIN
    dyn::POPUP "&New"
    dyn::BEGIN
      dyn::MENUITEM "&Empty file",1100
      dyn::POPUP "By template &file..."
      dyn::BEGIN
        dyn::MENUITEM "Template 1",1102,CHECKED
        dyn::MENUITEM "Template 2",1103
        dyn::MENUITEM "Template 3",1104
      dyn::ENDMenu
      dyn::MENUITEM "SEPARATOR"
      dyn::MENUITEM "Empty &window",1105
    dyn::ENDMenu
    dyn::MENUITEM "&Open..." tab "Ctrl+O",1110
    dyn::MENUITEM "&Save" tab "Ctrl+S",1111
    dyn::MENUITEM "Save &as..." tab "F12",1112
    dyn::MENUITEM "SEPARATOR"
    dyn::MENUITEM "E&xit" tab "Alt+F4",1180
  dyn::ENDMenu
  dyn::POPUP "&Edit"
  dyn::BEGIN
    dyn::MENUITEM "U&ndo" tab "Ctrl+Z",1200,GRAYED
    dyn::MENUITEM "SEPARATOR"
    dyn::MENUITEM "&Cut" tab "Ctrl+X",1201,GRAYED
    dyn::MENUITEM "C&opy" tab "Ctrl+C",1202,GRAYED
    dyn::MENUITEM "&Paste" tab "Ctrl+V",1203
    dyn::MENUITEM "SEPARATOR"
    dyn::MENUITEM "Select &all" tab "Ctrl+A",1204
  dyn::ENDMenu
  dyn::MENUITEM "&Compile!",1301
  dyn::MENUITEM "&Run!",1302
  dyn::POPUP "&Tools"
  dyn::BEGIN
    dyn::MENUITEM "&Compile" tab "F5",1301
    dyn::MENUITEM "&Run" tab "F6",1302
    dyn::MENUITEM "SEPARATOR"
    dyn::MENUITEM "&Edit Resources" tab "F7",1311
    dyn::MENUITEM "SEPARATOR"
    dyn::MENUITEM "Code &formatter...",1321
  dyn::ENDMenu
  dyn::POPUP "&Options"
  dyn::BEGIN
    dyn::MENUITEM "&Font settings...",1401
    dyn::MENUITEM "&General settings...",1402
    dyn::MENUITEM "&Project settings...",1403
    dyn::MENUITEM "SEPARATOR"
    dyn::MENUITEM "Auto &indent",1411
  dyn::ENDMenu
  dyn::POPUP "&Help"
  dyn::BEGIN
    dyn::MENUITEM "Help &keyword..." tab "F1",1900
    dyn::MENUITEM "&Basic help" tab "Shift+F1",1901
    dyn::MENUITEM "&API help" tab "Alt+F1",1902
    dyn::MENUITEM "&Editor help" tab "Ctrl+F1",1903
    dyn::MENUITEM "SEPARATOR"
    dyn::MENUITEM "Ab&out",1909
  dyn::ENDMenu
dyn::ENDMenu

In theory I can create a menu with 9 levels of submenus (which is nonsense). But I am surprised that it seems to be so easy to achieve this with OxygenBasic.

Attached is the enhanced dialogs.inc file and the Menu example. As you are a lot smarter than me maybe you will check the code of the helper functions for possible weaknesses? It would be great if the functions would be useable.

My next step will be to explore accelerators.

Roland

« Last Edit: January 25, 2018, 11:09:58 AM by Arnold »

jcfuller

  • Jr. Member
  • **
  • Posts: 85
Re: Using Dynamic Dialogs
« Reply #17 on: January 23, 2018, 04:19:00 AM »
Roland,
  Nice work.
I added:
Code: [Select]
$ filename "menu3.exe"
includepath "$/inc/"
#autodim off
#include "RTL64.inc"
#include "dialogs.inc"
To menu3.o2bas and compiled with:
exo2 -c
To create a 64bit version.

James

Arnold

  • Hero Member
  • *****
  • Posts: 510
Re: Using Dynamic Dialogs
« Reply #18 on: January 23, 2018, 05:35:37 AM »
Hi James,

yes, creating executables should be possible. Although I do not test this very much at the moment. With 32-bit executables there are problems from time to time with some Virus scanners which must be satisfied. (from time to time)

Although dialogs can be used independently to a certain degree, my intention is to use your Dlg2Src tool to create the Main Window with controls and WinMain / Wndproc, using dialogs as children and applying DlgProc. This would result in a very flexible and powerful teamwork. And ResEd would be the visual designer.

Roland

Arnold

  • Hero Member
  • *****
  • Posts: 510
Re: Using Dynamic Dialogs - Accelerators
« Reply #19 on: January 25, 2018, 11:15:59 AM »
Hello,

reading the W32Api Helpfile, this is what I learned about keyboard accelerators:
The function LoadAccelerators is used to load an accelerator table from a .rc file which is compiled to a .res file. This table is freed automatically when the app terminates.
The function CreateAcceleratorTable is used to create an accelerator table at run time using an array of ACCEL structures. Such a table must be destroyed with DestroyAcceleratorTable before the app terminates in order to omit memory leaks.
Interestingly I never noticed until now that the order of the records in an .rc file is different from the ACCEL structure:
.rc file:    key, cmd, fVirt
ACCEL:   fVirt, key, cmd

There are several methods to create the accelerators. Handwork is always necessary. I tried to use the records of the .rc file and then rearrange the order of the array members like ACCEL using a macro e.g.

Code: [Select]
   'Accelerators
   indexbase 0
   'order is like .rc file
   ACCEL accl[12] = {
   {79,            1110, FVIRTKEY | FCONTROL},
   {83,            1111, FVIRTKEY | FCONTROL},
   {VK_F12,        1112, FVIRTKEY},
   {87,            1221, FVIRTKEY | FALT},
   {VK_F5,         1301, FVIRTKEY},
   {67,            1301, FVIRTKEY | FALT},
   {VK_F6,         1302, FVIRTKEY},
   {82,            1302, FVIRTKEY | FALT},
   {VK_F7,         1311, FVIRTKEY},
   {VK_F1,         1901, FVIRTKEY | FSHIFT},
   {VK_F1,         1902, FVIRTKEY | FALT},
   {VK_F1,         1900, FVIRTKEY},
   {VK_F1,         1903, FVIRTKEY | FCONTROL}
   }
   'rearrange order like ACCEL structure
'   for x=0 to 12
'      swap accl(x).key, accl(x).cmd
'      swap accl(x).fVirt, accl(x).key
'   next
   dyn::alter(accl,12) 
   hAccel = CreateAcceleratorTable( @accl, 13 )

I have done this in the attached RichEdit example. In this example I also created a Popup Menu for right-click in the RichEdit control. Note: no special accelerator is necessary for Ctrl-Z, Ctrl-Y, Ctrl-C, Ctrl-V, Ctrl-X, Ctrl-A. The slightly modified dialogs.inc is attached too.

Roland
« Last Edit: January 25, 2018, 12:56:32 PM by Arnold »

Arnold

  • Hero Member
  • *****
  • Posts: 510
Re: Using Dynamic Dialogs
« Reply #20 on: January 26, 2018, 03:05:06 AM »
Hi Charles,

I would like to draw attention to a small issue which maybe is interesting for Oxygen in progress (I use the Latest Final Alpha).

In the Toolbar.o2bas example (Reply #2) I use in line 162: TOOLTIPTEXT pdi at lParam, which is defined in line 56. At the first time I forgot line 56, the result was increasing memory usage until Oxygen crashed. This can be observed with the Task Manager. (tested only with 32-bit Windows).

If I use line 163/164 instead of line 162 then I will get the expected error message. I will also get an error message if I use in line 152: NMHDRs pnm at lParam. So there must be a little difference in handling the line 152 and line 162.

The problem can be quickly located and solved. But maybe you want to know why there is a different behaviour of these two statements.

Roland

Charles Pegge

  • Author
  • *****
  • Posts: 3365
    • Oxygen Basic
Re: Using Dynamic Dialogs
« Reply #21 on: January 26, 2018, 08:20:03 AM »
Hi Roland,

Yes, there is a difference:

sys a
sys b at a
a and b retain their relationship, so that any change to a, will change the address of b, and vice-versa.

sys b at (a)

b will take the current value of a as its address. b will not be affected by later changes to a, and a will not be affected by changes to the address of b.

This is the same as:

sys *b = a
« Last Edit: January 26, 2018, 08:30:34 AM by Charles Pegge »

Arnold

  • Hero Member
  • *****
  • Posts: 510
Re: Using Dynamic Dialogs
« Reply #22 on: January 27, 2018, 04:13:16 AM »
Hi Charles,

there is a lot of information in your previous message, and most probably I still have not fully understood the principle. I tried this little code:

int a, b, c, d

sub change(int aa, *bb, *cc, *dd)
   aa=10 : print aa
'   int *a1=@aa : a1=100 : print a1
'   int a1 at @aa : a1=200 : print a1
   
   bb=20 : print bb
   int c1 at @cc : c1=30 : print c1
   int *d1=@dd   : d1=40 : print d1
end sub

change(a,b,c,d)

print a ", " b ", " c", " d

The values of b,c,d will be changed which is expected. But I cannot use e.g.
int *a1=aa: a1=100 : print a1
int a1 at aa
int c1 at cc
int *d1=dd

as this can be done with sys in case of lParam. I learned that lParam is a pointer, and wParam indicates handles and 32-bit (64-bit) values. The type sys seems to be a multipurpose instrument to fullfil the different interpretation as a value, address or pointer.

But anyway: I am not sure why line 152 will give an error message whereas line 162 does not. I could use any name in line 162 and there is no complaint, only a crash after some time. But NMHDR must be queried first, as this structure is the first member of several other structures.

At the moment I would tend to use these contstructs as they give a warning:

NMHDR *pnm=lParam
...
TOOLTIPTEXT *pdi=lParam

Roland




Charles Pegge

  • Author
  • *****
  • Posts: 3365
    • Oxygen Basic
Re: Using Dynamic Dialogs
« Reply #23 on: January 27, 2018, 06:42:39 AM »

int * a = b

The syntax is not perfect. It is more like a 'C' pointer definition, but it does the job.

Internally, this decomposes to:

int*a
@a=b


PS: Pointer variables always have 32/64 bit address pointers according to platform.
« Last Edit: January 27, 2018, 06:52:35 AM by Charles Pegge »

John

  • Hero Member
  • *****
  • Posts: 2843
Re: Using Dynamic Dialogs
« Reply #24 on: January 27, 2018, 02:45:43 PM »
Quote
It is more like a 'C' pointer definition

I thought it would be a good time to mention O2 can use C include files. This means standard libraries in C can be easily integrated with your O2 projects.

Arnold

  • Hero Member
  • *****
  • Posts: 510
Re: Using Dynamic Dialogs
« Reply #25 on: February 01, 2018, 01:42:18 AM »
Hi John,

you addressed a really important point and this should be discussed in a separate topic.

Roland

Arnold

  • Hero Member
  • *****
  • Posts: 510
Re: Using Dynamic Dialogs
« Reply #26 on: February 01, 2018, 02:17:47 AM »
Hi Charles,

I think I am done with my little project. I modified dialogs.inc to use only the constants, types and winapi functions to run dialogs.inc itself and added missing items in the examples separately. The zipped file contains the samples which I think are nice, I created it from a subfolder in one of the Oxygenbasic\Project folders. To run the batch file in ExeWithRes subfolder, dialogs.inc must be copied into this folder or into folder \inc. This time I did not use the namespace feature (only for dyn::init).

This is my conclusion:
I would only need Dialog, Control, Createmodeless and CreateModal function to create all possible controls. For InitCommonControlsEx it would be sufficient to use 0xffff to create all kind of classes. It would also be sufficient to use the strings for the classes.
Menus and accelerators could be done separately. So dialogs.inc could be very short. Nevertheless I learned about some connections between resource files and in-memory templates.
Perhaps there is something with this project which could be of general interest.

Roland 
« Last Edit: February 01, 2018, 02:34:25 AM by Arnold »

Charles Pegge

  • Author
  • *****
  • Posts: 3365
    • Oxygen Basic
Re: Using Dynamic Dialogs
« Reply #27 on: February 01, 2018, 05:17:10 AM »
Many thanks Roland,

I have put dialogs.inc into the inc folder, and all your examples into examples\WinDynDialogs. I also liked menus3.o2bas, so I've also included it (with DS_CENTER)

This is now included in OxygenBasicProgress.zip
https://github.com/Charles-Pegge/OxygenBasic




PS: Default parameters are now implemented for macros, as well as functions. I think this will produce more elegant macros. For instance:

Code: [Select]
macro init(tpl,b)
if tpl then freememory tpl
#ifdef b
  tpl=getmemory(b)
#else
  int b=1024
  tpl=getmemory(b)
#endif
end macro

reduces to:

Code: [Select]
macro init(tpl,b=1024)
if tpl then freememory tpl
tpl=getmemory(b)
end macro

John

  • Hero Member
  • *****
  • Posts: 2843
Re: Using Dynamic Dialogs
« Reply #28 on: February 01, 2018, 02:18:11 PM »
Quote
you addressed a really important point and this should be discussed in a separate topic.

The IUP interface is a good example of O2 using C include files.