LB Booster
Programming >> Compatibility with LB4 >> Liberty Composer
http://lbb.conforums.com/index.cgi?board=compatibility&action=display&num=1466275738

Liberty Composer
Post by Jack Kelly on Jun 18th, 2016, 6:48pm

Cundo has been working on a graphic window generator program which he has posted on the LB forum. I would like to run it on LBB but the generated code does not get the position and size of the controls. He says it works correctly on LB45. I have worked for several hours unsucessfully trying to figure out why. Three clicks shows the problem -- Menu, add button, Produce Code. The code is printed to MainWin.

Code:
'Drag the controls, clicking on them. Resize them clicking the little square 
'at the bottom of each control. Right click deletes the control below the 
'cursor.
app$= "Liberty Composer v111"
'   (Previously named: Super simple visual designer)
'   (c) 2016 by cundo
'   Find discussion and updates if any at : libertybasic.conforums.com
    global control, grid, avoidList$
    dim controlType$(100)
    grid=24
    WindowWidth = 640 : WindowHeight = 480
    UpperLeftX = INT((DisplayWidth-WindowWidth)/2)
    UpperLeftY = INT((DisplayHeight-WindowHeight)/2)
    width=WindowWidth-150 : height=WindowHeight-150
    stylebits   #main.gbx,_WS_SIZEBOX OR _WS_BORDER or _WS_CAPTION, 0, 0, 0
    graphicbox  #main.gbx, WindowWidth/2-width/2, WindowHeight/2-height/2, width, height
    stylebits   #main.add, 0, 0, 0, 0
    button      #main.add,"&Menu",[addControl],ul,1,1,50,28
    button      #main.en,"&Enable all",[enableControls],ul,100,1,75,28
    button      #main.code,"&Produce Code",  [code],ul,176,1,150,28
    Open app$ For window As #main
    call DrawGrid "#main.gbx",width*2,height*2
    #main "trapclose quit"
    wait

  [code]
cls

    Call GetRect hWnd(#main.gbx),winx,winy,winwidth,winheight
    Print "NoMainWin"

    Print "WindowWidth = ";winwidth ;" : WindowHeight = " ;winheight
    Print "UpperLeftX = INT((DisplayWidth-WindowWidth)/2)"
    Print "UpperLeftY = INT((DisplayHeight-WindowHeight)/2)"
    Print

 for i = 1 to control
   if instr(avoidList$,";#";i)=0 then
    h$= "#";i;".b1"
    call GetRect hWnd(#h$),nul  , nul , codewidth ,codeheight
    h =  hWnd(#main.gbx)
    Calldll #user32, "ScreenToClient",h As ulong,Rect As struct,result as void
    codex=Rect.x1.struct
    codey=Rect.y1.struct

    print controlType$(i);",";str$(codex);",";str$(codey);_
    ",";str$(codewidth);",";str$(codeheight)
'    print controlType$(i);",";str$(px);",";str$(py);_
'    ",";str$(controlWidth);",";str$(controlHeight)
  end if
 next i

    Print
    Print "Open ";chr$(34);"Window";chr$(34);" for Window as #main"
    Print "#main ";chr$(34);"trapclose [quit]";chr$(34)
    Print "wait"
    Print
    Print "[quit]"
    Print "close #main"
    Print "End"

wait

[enableControls]
if control then
    #main.en word$("&Disable all; &Enable all",areOn+1,";")
    areOn = abs(not(areOn))
    for i = 1 to control
        EnableThisHandle$ = "#";i;".b1"
        EnableThisWHandle$= "#";i
        call EnableWindow hWnd(#EnableThisHandle$), areOn
    next
end if

wait

[addControl]
    color$="BUTTONFACE"
    controlWidth=100 : controlHeight=30
    px= int(rnd(0)*(400-controlWidth))
    py= int(rnd(0)*(300-controlHeight-30))
    WindowWidth =controlWidth : WindowHeight = controlHeight
    dim array$(10)
    for i = 1 to 10
     array$(i)="Drag me please"
    next
    stylebits #101.gfx, 0, _WS_BORDER, 0, 0
    stylebits #101.b1, _WS_DISABLED, 0, 0, 0
    gfxw=controlWidth : gfxh=controlHeight
    graphicBox  #101.gfx, px,py,gfxw+9,gfxh+9
    popupmenu "add button",[buttonCode],"add textbox",[txtCode],_
        "add listbox",[listCode],"add static",[staticCode],_
         "add combobox",[comboCode],"add radiobutton",[radioCode],_
          "add texteditor",[edCode],"add checkbox",[chkCode],_
           "add graphicbox",[blank]
    wait

[buttonCode]
    type$="button #main.b";control+1;",";chr$(34);"Button";chr$(34);_
    ", [quit],ul"
    button  #101.b1,"Drag me ";control+1,dummy,ul,_
    0,0,controlWidth,controlHeight :goto [createWindow]
[txtCode]
    type$="textbox #main.tb";control+1
    textbox #101.b1,0,0,controlWidth,controlHeight : goto [createWindow]
[listCode]
    type$="listbox #main.lbx";control+1;",ar$(,dummy"
    listbox #101.b1, array$(), dummy,_
     0, 0, controlWidth, controlHeight : goto [createWindow]
[staticCode]
    type$="statictext #main.st";control+1;",";chr$(34);"static";chr$(34)
    statictext #101.b1,"Drag me",_
    0,0,controlWidth,controlHeight  : goto [createWindow]
[comboCode]
    type$="combobox #main.combo";control+1;",ar$(,dummy"
    combobox #101.b1, array$(), dummy,_
     0, 0, controlWidth, controlHeight  : goto [createWindow]
[radioCode]
    type$="radiobutton #main.rb";control+1;",";chr$(34);"Radio";chr$(34);_
    ",dummy,dummy"
    radiobutton #101.b1, "Drag me", dummy, dummy,_
     0, 0, controlWidth, controlHeight  : goto [createWindow]
[edCode]
    type$="texteditor #main.txt";control+1
    texteditor #101.b1, 0, 0,_
     controlWidth, controlHeight  : goto [createWindow]
[chkCode]
    type$="checkbox #main.rb";control+1;",";chr$(34);"Radio";chr$(34);_
          ",dummy,dummy"
    checkbox #101.b1, "Drag me", dummy, dummy,_
     0, 0, controlWidth, controlHeight : goto [createWindow]
[blank]
    type$="graphicbox #main.gbx";control+1
    stylebits #101.b1, _WS_BORDER OR _WS_DISABLED, 0, 0, 0
    ' dummy control, I just need a 'b1' control
    statictext #101.b1,"",0,0,controlWidth,controlHeight
   ' stylebits #101.gfx, 0,0,0,0 : color$="WHITE;|";chr$(13);"hello"

[createWindow]
    ' needs a menu supported window to avoid an error.log entry
    ' 'Kill BASIC Apps'
    stylebits #101, _WS_SYSMENU, _WS_VISIBLE,0, 0
    Open "" For window_popup As #101
    #101.gfx "down;fill ";color$
    #101.gfx "place ";gfxw;" ";gfxh
    call Draw "#101.gfx", gfxw, gfxh
    #101.gfx "When leftButtonMove lbm"
    #101.gfx "When rightButtonDown delete"
    call setParent hWnd(#101.gfx),hWnd(#101.b1)
    call setParent hWnd(#main.gbx),hWnd(#101.gfx)
    control=control+1
    controlType$(control)=type$
    newHandle$="#";control
    maphandle #101,newHandle$
Wait

Sub quit h$
    for i  = 1 to control
       newHandle$="#";i
       if instr(avoidList$,newHandle$)=0 then
        close #newHandle$ 
       end if
    next
   close #main
 End
End Sub

Sub lbm h$, X, Y
handler$ = Word$(h$, 1, ".")
hWnd = hWnd(#h$)
'print h$,handler$

    CallDll #user32, "ReleaseCapture",r As void
    Call GetRect hWnd, nul  , nul , w ,h

    q=_HTCAPTION  'by default, grab the window
    if abs(w-X)<=10 AND abs(h-Y)<=10 then
            ' the lower right corner
            ' means a resize event
            q=_HTBOTTOMRIGHT
    end if

 CallDLL #user32, "SendMessageA", _
    hWnd As ULong, _
    _WM_NCLBUTTONDOWN As ULong, _
    q As uLong, _
    0 As Long, _
    r As void

    'also resize the control inside the graphicbox
    if q=_HTBOTTOMRIGHT then
        Call GetRect hWnd, nul  , nul , w ,h
        w=w-9 : h = h-9
        b1h$ = handler$;".b1"
        b1h = hwnd(#b1h$)
        call MoveWindow b1h,0,0,w,h
        call Draw h$,w,h
    end if

        ' align to grid
        Call GetRect hWnd, nul  , nul , w ,h
        main = hWnd(#main.gbx)
        Calldll #user32, "ScreenToClient",main As ulong,Rect As struct,result as void
        x1 = int(Rect.x1.struct/grid)*grid
        y1 = int(Rect.y1.struct/grid)*grid
        Call MoveWindow hWnd,x1,y1, w, h

End Sub

Sub delete h$,x,y
    win$ = word$(h$,1,".")
    n$=word$(h$,2,".")
    confirm "Delete this control?"; responseVar$
     If responseVar$="yes" Then
        close #win$ 
        avoidList$=avoidList$;";";win$
     End if
End Sub
Sub dummy h$
End Sub
Sub setParent parent,child
    calldll #user32, "SetParent",_
        child as ulong,_
        parent as ulong,_
        r as void
End Sub
Sub ShowWindow hWnd, flag
    CallDLL #user32, "ShowWindow",_
    hWnd as uLong, flag As uLong,_
    r As void
End Sub
Sub EnableWindow hWnd, flag
    CallDLL #user32, "EnableWindow",_
     hWnd as uLong, flag As uLong,_
     r As void
End Sub
Sub GetWindowRect hW
    struct Rect, x1 As Long, y1 As Long, x2 As Long, y2 As Long
    CallDLL #user32, "GetWindowRect",_
    hW as uLong,Rect As struct, result As void
End Sub
Sub Draw h$,x,y
        #h$ "cls;fill buttonface;";_
            "place ";x-1;" ";y-1
        #h$ "color buttonface"
        #h$ "backcolor buttonface"
        #h$ "rule ";_R2_NOT
        #h$ "boxfilled ";x+5;" ";y+5
        #h$ "line ";x;" ";y+2;" ";x+5;" ";y+2
        #h$ "line ";x+2;" ";y;" ";x+2;" ";y+5
        #h$ "flush"
End sub
Sub DrawGrid h$,width,height
        #h$ "cls"
        #h$ "down;fill buttonface ;flush"
        #h$ "size 1;color BLACK"
        for x = 0 to width step grid
         for y = 0 to height step grid
             #h$ "set ";x;" ";y
        next:next
        #h$ "flush;up"
        #h$ "setfocus"
End Sub
Sub MoveWindow hnd,x,y,w,h
        calldll #user32, "MoveWindow",_
        hnd as ulong, _       'window handle
        x as long,_            'x location of gfx window
        y as long,_            'y location of gfx window
        w as long,_           'desired width of window
        h as long,_           'desired height of window
        1 as long,_             'repaint flag,0=false,1=true
        ret as void             'nonzero=success
End Sub

Sub GetRect hnd, byref x  , byref y , byref w ,byref h
    call GetWindowRect hnd
    x= Rect.x1.struct
    y= Rect.y1.struct
    w= Rect.x2.struct-Rect.x1.struct
    h= Rect.y2.struct-Rect.y1.struct
End SUb
'include lb45func.bas
 

Re: Liberty Composer
Post by Richard Russell on Jun 18th, 2016, 8:13pm

on Jun 18th, 2016, 6:48pm, Jack Kelly wrote:
I have worked for several hours unsucessfully trying to figure out why.

It's a documented incompatibility. In fact it's item 4 in the Compatibility section of the LBB docs:

"Child control handles must be mapped explicitly, e.g. MAPHANDLE #old.te,#new.te; mapping the parent window's handle is not sufficient".

So to make the program work correctly in LBB you need to replace this line (154):

Code:
    maphandle #101,newHandle$ 

with this Code:
    maphandle #101.b1,newHandle$;".b1"
    maphandle #101.gfx,newHandle$;".gfx"
    maphandle #101,newHandle$ 

This modification is compatible with LB, so may safely be left in the program.

Richard.

Re: Liberty Composer
Post by Jack Kelly on Jun 18th, 2016, 10:12pm

Thank you, Richard, for coming to my rescue AGAIN. I am grateful for your help!
Re: Liberty Composer
Post by Richard Russell on Jun 21st, 2016, 9:20pm

on Jun 18th, 2016, 6:48pm, Jack Kelly wrote:
Cundo has been working on a graphic window generator program which he has posted on the LB forum.

There's a comment over at the LB Community Forum as follows: "When you right click a control, what it does is to close the hidden window which is holding it.... then the control disappears".

This analysis seems to be based on the assumption that the "control" is a child of the "hidden window" - but it isn't! When originally created that is the case, but the program uses the SetParent API to change the control's parent from the hidden window to the main graphicbox!

So when you right-click and request that the control be deleted, the hidden window is closed as expected, but the control does not disappear because it is no longer a child of that hidden window.

The solution is to restore the original parent-child relationship before the parent window is closed, then the control does indeed disappear:

Code:
Sub delete h$,x,y
    win$ = word$(h$,1,".")
    n$=word$(h$,2,".")
    confirm "Delete this control?"; responseVar$
     If responseVar$="yes" Then
        hp = hwnd(#win$)
        hc = hwnd(#h$)
        call setParent hp, hc ' restore parent-child relationship
        close #win$
        avoidList$=avoidList$;";";win$
     End if
End Sub 

The interesting thing is that, apparently, in LB 4.5.0 the control does disappear, despite not being a child of the window that is closed. Why?

Richard.
Re: Liberty Composer
Post by Jack Kelly on Jun 22nd, 2016, 11:26am

Thanks for following up with this, Richard. I'm really having a lot of fun enhancing this program. As I've said previously, I am better at orchestration than composition. I hope to use the program extensively in my future development projects. I'd really like to post my version, but I don't think cundo would appreciate that.
Re: Liberty Composer
Post by Richard Russell on Jun 22nd, 2016, 11:59am

on Jun 22nd, 2016, 11:26am, Jack Kelly wrote:
I'd really like to post my version, but I don't think cundo would appreciate that.

Really? Is he claiming Copyright infringement or something? Usually when people post code to forums they encourage others to improve on it!

What aspects of cundo's program do you feel make it better than FreeForm? That's Open Source so I think anybody can publish modified versions so long as the Copyright notice is retained.

Richard.

Re: Liberty Composer
Post by Jack Kelly on Jun 22nd, 2016, 1:05pm

I've never been able to get FreeForm to run. I always seem to be missing some file that I can't manage to find. Once when I did get it to run under JB, it seemed a bit creaky and quirky.

I can't run LB anymore on my system. The trial period has expired and I have no intention of paying for it.
Re: Liberty Composer
Post by Richard Russell on Jun 22nd, 2016, 2:25pm

on Jun 22nd, 2016, 1:05pm, Jack Kelly wrote:
I've never been able to get FreeForm to run. I always seem to be missing some file that I can't manage to find.

FreeForm uses several bitmap files in LB's bmp folder so it is necessary to have LB installed (it doesn't matter if the trial period has expired). So download FreeForm_LBB.bas to the folder where LB's example programs are - that will probably be %appdata%\Liberty BASIC v4.04\ or %appdata%\Liberty BASIC v4.5.0\ depending on what version it is, and run it using LBB.

That should give you a working version of FreeForm that does not depend on LB, except for the bitmap files. You could always replace those with your own custom versions if you want to be entirely independent of LB. FreeForm states specifically that it is Open Source so there shouldn't be any IPR issues so long as you retain the Copyright notice.

Quote:
Once when I did get it to run under JB, it seemed a bit creaky and quirky.

The JB version of FreeForm is significantly different from the LB version.

Richard.
Re: Liberty Composer
Post by Jack Kelly on Jun 23rd, 2016, 11:19am

I got Freeform up and running thanks to your excellent directions, Richard. My initial impression is that it's everything for everybody but perhaps a bit too much for me personally. Cundo's Liberty Composer is now tailored to the way I like to work, and the code is almost understandable. However, I will continue to evaluate Freeform and perhaps take some of its features over to LC, if possible. Thanks again for all your support. It's truly a privilege to be able to work with you.