simple GTWVG sample code?

2,187 views
Skip to first unread message

Pete

unread,
May 28, 2020, 6:27:30 AM5/28/20
to Harbour Users
Hi all,

Any gtwvg power user around here? ;-)

I've been asked to renovate an old (but reliably working) application.
I'm thinking to add some GUI "bells & whistles", starting from a (windows like) GUI Menu.
The rest UI will be remain as is, and gradually in the future I'll, possibly, add, some additional
GUY elements. For now, that's all I want to do. Just a GUI menu.
The question(s) is, is it possible to be done as described and if yes,
has anybody got (and wants to share) a `SIMPLE` sample code, for this thing?
I've looked in `gtwvg\tests` but I found it a little-bit more complicated than I wished it to be.
Any contribution, "as simple as possible and even more simple", is very welcome!

regards,
Pete



jlca...@gmail.com

unread,
May 28, 2020, 7:21:34 AM5/28/20
to Harbour Users
Hi, take a look at E:\hb34\tests\wvtext.prg

You wvtext.prg will probably be in a different location on your system.

It is a Harbour Extended GT Features Demo



Joe

Ash

unread,
May 28, 2020, 7:40:53 AM5/28/20
to Harbour Users
Hello Pete,

I have built and successfully used a tool, WVWClip, for doing just what you are about to do but it is based on GTWVW. Good part is that your original Clipper code will require minimum of changes. I can share my work with you.

Regards.
Ash 

jlca...@gmail.com

unread,
May 28, 2020, 7:45:32 AM5/28/20
to Harbour Users
Here is a link to some detailed info about hb_gtinfo;


hb_gtinfo is used in the Harbour Extended GT Features Demo that I mentioned.

Joe

On Thursday, 28 May 2020 06:27:30 UTC-4, Pete wrote:

José Quintas

unread,
May 28, 2020, 7:49:14 AM5/28/20
to harbou...@googlegroups.com

Are you sure?

GUI menu is a bad thing.

Check on samples the function buildmenu()

Not sure if this can help, because I use a recursive array.

STATIC FUNCTION MenuWvg( mMenuOpt )

   LOCAL oMenu

   oMenu  := wvgSetAppWindow():MenuBar()
   BuildMenu( oMenu, mMenuOpt )
...

FUNCTION BuildMenu( oMenu, acMenu )

   LOCAL oElement, oSubMenu, cbCode, m_ProgTxt

   FOR EACH oElement IN acMenu
      IF Len( oElement[ 2 ] ) == 0
         m_Prog := oElement[ 3 ]
         IF ValType( m_Prog ) == "C"
            cbCode     := [{ || RunModule( "] + m_Prog + [", "] + m_ProgTxt + [" ) }]
            oMenu:AddItem( oElement[ 1 ] , &( cbCode ) )
         ELSE
            oMenu:AddItem( oElement[ 1 ], oElement[ 3 ] )
         ENDIF
      ELSE
         oSubMenu := WvgMenu():new( oMenu, , .T. ):Create()
         BuildMenu( oSubMenu, oElement[ 2 ] )
         oMenu:AddItem( oSubMenu, oElement[ 1 ] )
      ENDIF
   NEXT

   RETURN NIL


Array have this format:

{ cCaption, {}, cModule }


Second parameter may be another array with same format, with a submenu.

Third parameter may be a text or a codeblock


José M. C. Quintas

Pritpal Bedi

unread,
May 28, 2020, 8:47:59 AM5/28/20
to Harbour Users
Hi Pete

Just remove or comment-out these lines from demowvg.prg. and you will get a pure console window without GETs GUIed.



   oLastMenu:disableItem( 11 )
   oLastMenu:checkItem( 1 )
   oLastMenu:insItem( 11, { "I am inserted later !", ;
      {|| wvg_MessageBox( , "Hi " + iif( oLastMenu:isItemChecked( 1 ), "Yes", "No" ) + ;
      iif( oLastMenu:isItemEnabled( 12 ), " Yes", " No" ) ) } } )

   oLastMenu:setItem( 14, { "This is Set Against Prev Menu", {|| wvg_MessageBox( , "Hi" ) } } )

   SetMode( MaxRow() + 1, MaxCol() + 1 )  /* Needed to accommodate attached menu */

   SetKey( K_F12        , {|| hb_gtInfo( HB_GTI_ACTIVATESELECTCOPY ) } )
   SetKey( K_CTRL_V     , {|| __Keyboard( hb_gtInfo( HB_GTI_CLIPBOARDDATA ) ) } )
   SetKey( K_RBUTTONDOWN, {|| __Keyboard( hb_gtInfo( HB_GTI_CLIPBOARDDATA ) ) } )

   hPopup := wvt_SetPopupMenu()

   pGT := SetGT( 1, hb_gtSelect() )

   /* Force mouse pointer right below the Harbour label */
   wvt_SetMousePos( 2, 40 )

   AAdd( aBlocks, {|| wvt_SetIcon( GetResource( "vr_1.ico" ) ) } )
   AAdd( aBlocks, {|| Wvt_SetTitle( "Vouch" ) } )
   AAdd( aBlocks, {|| wvt_DrawLabel( 1, 40, cLabel, 6,, RGB( 255, 255, 255 ), RGB( 198, 198, 198 ), "Arial", 26, , , , , .T., .T. ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxRaised( nTop, nLft, nBtm, nRgt ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxRecessed( 7, 61, 13, 70 ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxGroup( 15, 59, 18, 72 ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxGroup( 5, 6, 19, 44 ) } )
   AAdd( aBlocks, {|| wvt_DrawImage( 8, 62, 12, 69, IMAGE_VOUCH, , .T. ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxRecessed( 7, 48, 13, 55 ) } )
   AAdd( aBlocks, {|| wvt_DrawLine( MaxRow() - 2, 0, MaxRow() - 2, MaxCol(), WVT_LINE_HORZ, WVT_LINE_RECESSED, WVT_LINE_BOTTOM ) } )
   AAdd( aBlocks, {|| wvt_DrawLine( MaxRow() - 1, 41, MaxRow(), 41, WVT_LINE_VERT, WVT_LINE_RECESSED, WVT_LINE_CENTER ) } )
   AAdd( aBlocks, {|| AEval( GetList, {| oGet | wvt_DrawBoxGet( oGet:Row, oGet:Col, Len( Transform( oGet:VarGet(), oGet:Picture ) ) ) } ) } )

   AAdd( aBlocks, {|| wvt_Mouse( -1000001 ) } )

   aLastPaint := WvtSetBlocks( aBlocks )

   /* Xbase++ compatible pure GUI controls onto CUI console */
   BuildButtons()


It is as simple as that. GUI controls are glued on top of pure character interface. You need not to if so desired.


Pritpal Bedi
a student of software analysis & concepts

Ash

unread,
May 28, 2020, 10:25:18 AM5/28/20
to Harbour Users
Hello Pete,

One lesson I learnt when GUIfying a large business application, was to make as little a change as possible to the existing code. Best results are possible by redefining a Clipper command (@...GET, for example) so it uses GTWVG or GTWVW functions under the hood to achieve the same results. Thus reducing the conversion effort.

Regards.
Ash 

 




keep the code as close to clipper syntax as possible.  

Pete

unread,
May 29, 2020, 3:15:28 AM5/29/20
to Harbour Users
Hi Ash,

I have built and successfully used a tool, WVWClip, for doing just what you are about to do but it is based on GTWVW.
Good part is that your original Clipper code will require minimum of changes. I can share my work with you.

Very interesting and kind offer! I'm waiting to try your WVW tool,
(as well as, to find out how much "minimum" is the "minimum" in your part of world! ;-))

regards,
Pete

Pete

unread,
May 29, 2020, 3:16:59 AM5/29/20
to Harbour Users
Hi,

> Here is a link to some detailed info about hb_gtinfo;
> https://github.com/zgamero/sandbox/wiki/HB_GT_INFO

Thank you for reminding this! I was and still am fun of this "Sandbox".
Great (and accurate!) source of info for various harbour things.

regards,
Pete

Pete

unread,
May 29, 2020, 3:19:21 AM5/29/20
to Harbour Users
Hi Jose,

 GUI menu is a bad thing.

Possibly, but it's fancy and I hope it will me help to stop the mutter by users
about "ancient", "Dos like" look and feel of the application.

Check on samples the function buildmenu()
Not sure if this can help, because I use a recursive array.

I was not able to figure out how to use your sample code.
I must say I have almost zero knowledge about gtwvg,
and my (hard) experience over the years has taught me that
the greatest help for a newbie in some programming subject,
is a `Short, Self Contained, Compilable, Example` and that's
what I was looking for, to get started.
By the way, in my humble opinion, the number of available such a `Short,
Self Contained, Compilable, Examples` is the indispensable  "ticket for the success"
for any development tool. I'm absolutely convinced about this simple truth!

regards,
Pete

Pete

unread,
May 29, 2020, 3:21:18 AM5/29/20
to Harbour Users
Hi Pritpal,
many thanks for getting the time to reply, very appreciated!

I followed your hints and got somewhere near to what I'm looking for.
However, I need to study how the menu mechanism is being implemented, i.e.,
what would be the main loop where we catch the various events
(key-presses, user selections, mouse clicks etc) to properly handle them,
as well how we recognize those events (key-codes etc).
Obviously I have to spend a little more time on it.
Thank you very much, for all the support over the years and your great
contribution to harbour-project (particularly, this harupdf adaptation is awesome!)

regards,
Pete

Pritpal Bedi

unread,
May 29, 2020, 2:53:38 PM5/29/20
to Harbour Users
Hi Pete

Look at this function which is self-explanatory.

But this menu option may be special - as you want to intercept inkey() loop:

   oMenu:AddItem( "Exit"                        , {|| __Keyboard( K_ESC ) } )

Vis this mechanism you can push keys in keyboard buffer and handled via inkey(). Is this sufficient ?



STATIC FUNCTION BuildMainMenu()

   LOCAL oMenu
   LOCAL g_oMenuBar := WvgSetAppWindow():menuBar()

   oMenu := WvgMenu():new( g_oMenuBar, , .T. ):create()
   oMenu:Caption := "Wvt*Classes"
   oMenu:AddItem( "Dialog One . New Window . Threaded"       , {|| DialogWvgClassesOne( 1 ) } )
   oMenu:AddItem( "Dialog One . Main Window . Primary Thread", {|| DialogWvgClassesOne( 2 ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Dialog Two"                  , {|| DialogWvgClassesTwo()       } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Exit"                        , {|| __Keyboard( K_ESC ) } )
   g_oMenuBar:addItem( { oMenu, "Wvt*Classes" } )

   oMenu := WvgMenu():new( g_oMenuBar, , .T. ):create()
   oMenu:caption := "Traditional"
   oMenu:AddItem( "Gets . GTWVG . Threaded"     , {|| WvtNextGets()       } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Gets . GTWVT . Threaded"     , {|| WvtConsoleGets( 0 ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Browser . GTWVG . Threaded " , {|| WvtMyBrowse()       } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Partial Screen . Main Window", {|| WvtPartialScreen()  } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Wvt Lines . Main Window"     , {|| WvtLines()          } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Online Maps"                 , {|| WvtConsoleGets( 1 ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Wvg Console with GCUI"       , {|| ExecGCUI()          } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Modal Window"                , {|| DoModalWindow()     } )
   g_oMenuBar:addItem( { oMenu, "Traditional" } )

   oMenu := WvgMenu():new( g_oMenuBar, , .T. ):create()
   oMenu:Caption := "Common Dialogs"
   oMenu:AddItem( "Fonts"                       , {|| wvt_ChooseFont()  } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Colors"                      , {|| wvt_ChooseColor() } )
   g_oMenuBar:addItem( { oMenu, "Common Dialogs" } )

   oMenu := WvgMenu():new( g_oMenuBar, , .T. ):create()
   oMenu:Caption := "Functionality"
   oMenu:AddItem( "Expand"                      , {|| WvtWindowExpand(  1 ) } )
   oMenu:AddItem( "Shrink"                      , {|| WvtWindowExpand( -1 ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Minimize"                    , {|| wvt_Minimize()   } )
   oMenu:AddItem( "Maximize"                    , {|| hb_gtInfo( HB_GTI_SPEC, HB_GTS_WNDSTATE, HB_GTS_WS_MAXIMIZED ) } )
   g_oMenuBar:addItem( { oMenu, "Functionality" } )

   oMenu := WvgMenu():new( g_oMenuBar, , .T. ):create()
   oMenu:Caption := "Modeless Dialogs"
   oMenu:AddItem( "Dynamic Dialog . Modeless"   , {|| DynWinDialog( 1 ) } )
   oMenu:AddItem( "Dynamic Dialog . Modal "     , {|| DynWinDialog( 2 ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "Slide Show . Modeless"       , {|| DlgSlideShow()   } )
   g_oMenuBar:addItem( { oMenu, "Modeless Dialogs" } )

   oMenu := WvgMenu():new( g_oMenuBar, , .T. ):create()
   oMenu:Caption := "~XbpDialog()s"
   oMenu:AddItem( "Pure Xbase++"                , {|| hb_threadStart( {|| demoXbp() } ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "ActiveX - Internet Explorer" , {|| hb_threadStart( {|| ExecuteActiveX(  1 ) } ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "ActiveX - Visualize a PDF"   , {|| hb_threadStart( {|| ExecuteActiveX(  3 ) } ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "ActiveX - Explorer . DHTML"  , {|| hb_threadStart( {|| ExecuteActiveX( 11 ) } ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "ActiveX - RMChart"           , {|| hb_threadStart( {|| ExecuteActiveX(  4 ) } ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "ActiveX - Analog Clock"      , {|| hb_threadStart( {|| ExecuteActiveX(  2 ) } ) } )
   oMenu:AddItem( "-" )
   oMenu:AddItem( "ActiveX - Image Viewer"      , {|| hb_threadStart( {|| ExecuteActiveX(  5 ) } ) } )
   g_oMenuBar:addItem( { oMenu, "~XbpDialog()s" } )

   RETURN oMenu  /* The last submenu item */

Pete

unread,
May 30, 2020, 6:25:57 AM5/30/20
to Harbour Users
Hi Pitrpal,

On Friday, 29 May 2020 21:53:38 UTC+3, Pritpal Bedi wrote:
Hi Pete

Look at this function which is self-explanatory.

But this menu option may be special - as you want to intercept inkey() loop:

   oMenu:AddItem( "Exit"                        , {|| __Keyboard( K_ESC ) } )

Vis this mechanism you can push keys in keyboard buffer and handled via inkey(). Is this sufficient ?



Maybe, but I don't know how to use it. :-(
I have to try it, which I will do during this weekend.
In the meant time, I have prepared a small sample of a menu similar to what I  use in non-gui applications. What I am trying to achieve (and that was the aim to start this thread) is to "transform" this TUI menu into GUI style menu, like that we see in `demowvg.prg`.
Just that!
the rest of code shall remain as is, no GUI elements for now.
Is it possible?

 I attach the sample code, in hope somebody could GUIfy it.

regards,
Pete
menu.prg.txt

Ash

unread,
May 30, 2020, 10:27:09 AM5/30/20
to Harbour Users
Hello Pete,

Attached is a sample application using GTWVG. It uses ideas from WVWClip. Please compile as shown below.

hbmk2 wvgclip.hbp

Regards.
Ash
wvgclip.zip

Francesco Perillo

unread,
May 30, 2020, 11:59:08 AM5/30/20
to harbou...@googlegroups.com
Pete,
I invite you to think twice about switching the menu system.
My program has a very basic, let's say "3270 era" menu system. Everytime you make a selection, a new menu opens, nidified. In this way users can - from whatever point in the menu system they are, just press ESC several times (ESC exits the current menu and control returns to the previous) up to the main menu (ESC doesn't working on main menu).
So, to create an invoice, from any menu they are they can press ESC ESC ESC ESC ESC 4 1 1 and the "emit invoice form opens". or ESC ESC ESC ESC 6 3 1 to open the form to check if a client have sums to pay...
I think that forcing them to use mouse may make them lose time...

What to do when you open a form for creating a invoice? would you disable the menu until the form is closed? Or would you start using MT to have several forms opened (it would be my dream)?


--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/harbour-users/edfd8c83-81ba-4f28-9936-adb26d3dce5a%40googlegroups.com.

José Quintas

unread,
May 30, 2020, 9:12:44 PM5/30/20
to harbou...@googlegroups.com
Em 30/05/2020 12:59, Francesco Perillo escreveu:
>
>
> What to do when you open a form for creating a invoice? would you
> disable the menu until the form is closed? Or would you start using MT
> to have several forms opened (it would be my dream)?
>
>

I do not understand about "my dream".

You can use wvgcrt() or hb_gtReload()

José M. C. Quintas

Ash

unread,
May 30, 2020, 9:52:20 PM5/30/20
to Harbour Users
Hello Francesco,

Attached is how my multiuser application screen looks like. Toolbar allows quick access to frequently used transactions and queries. I can always open another instance of my application if needed.

Regards.
Ash



On Saturday, May 30, 2020 at 11:59:08 AM UTC-4, fperillo wrote:
Pete,
I invite you to think twice about switching the menu system.
My program has a very basic, let's say "3270 era" menu system. Everytime you make a selection, a new menu opens, nidified. In this way users can - from whatever point in the menu system they are, just press ESC several times (ESC exits the current menu and control returns to the previous) up to the main menu (ESC doesn't working on main menu).
So, to create an invoice, from any menu they are they can press ESC ESC ESC ESC ESC 4 1 1 and the "emit invoice form opens". or ESC ESC ESC ESC 6 3 1 to open the form to check if a client have sums to pay...
I think that forcing them to use mouse may make them lose time...

What to do when you open a form for creating a invoice? would you disable the menu until the form is closed? Or would you start using MT to have several forms opened (it would be my dream)?


On Thu, May 28, 2020 at 12:27 PM Pete <pete...@gmail.com> wrote:
Hi all,

Any gtwvg power user around here? ;-)

I've been asked to renovate an old (but reliably working) application.
I'm thinking to add some GUI "bells & whistles", starting from a (windows like) GUI Menu.
The rest UI will be remain as is, and gradually in the future I'll, possibly, add, some additional
GUY elements. For now, that's all I want to do. Just a GUI menu.
The question(s) is, is it possible to be done as described and if yes,
has anybody got (and wants to share) a `SIMPLE` sample code, for this thing?
I've looked in `gtwvg\tests` but I found it a little-bit more complicated than I wished it to be.
Any contribution, "as simple as possible and even more simple", is very welcome!

regards,
Pete



--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.

Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbou...@googlegroups.com.
Screen Shot 2020-05-30 at 9.46.30 PM.png

Pete

unread,
May 31, 2020, 2:18:45 PM5/31/20
to Harbour Users
Hi Francesco,


On Saturday, 30 May 2020 18:59:08 UTC+3, fperillo wrote:
Pete,
I invite you to think twice about switching the menu system.

Yes, but I don't want to change the menu. Just to apply some "fresh" (read 'window-ish') look onto the already existent.
Without any other change by now. If it's possible! If it's not, thing remain 'as is'.
 
My program has a very basic, let's say "3270 era" menu system. Everytime you make a selection, a new menu opens, nidified. In this way users can - from whatever point in the menu system they are, just press ESC several times (ESC exits the current menu and control returns to the previous) up to the main menu (ESC doesn't working on main menu).

Oh man! this reminds me some "illustrious" RPG-II days, on an S/36 IBM system,
(was beginning of '90s, very young with much zest to learn the secrets of these alien beasts).

The  problem is that this UI model, while simple and stable, not "sells" anymore, mainly because
the keyboard driven applications are forced to extinction by mouse-able and touchable ones.
You certainly know, it's a slow paced process started with earliest windows and coming to a near ending.
It's been said, "the main problem of the new technology is the more new technology!" ;-)
I find quite annoying the fact that old good technology goes to recycle-bin, usually for non really beneficial reasons
but it's a compulsive process pushed by the big players in their try to help their (fat) incomes. 
 
... Or would you start using MT to have several forms opened (it would be my dream)?

MT? if you mean "Multi-Threading" then "hmm..! is it necessary?" In my humble (and not expert) opinion, MT is a special
technique for special purposes.but who wants to sail risky waters, when there's no special need to do so?

regards,
Pete

Francesco Perillo

unread,
May 31, 2020, 2:29:50 PM5/31/20
to harbou...@googlegroups.com
Ash, is your software MT? Can you have multiple active windows open at the same time?


Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/harbour-users/491efe82-d6de-4982-9e4d-93d9998191fb%40googlegroups.com.

Pete

unread,
May 31, 2020, 2:33:35 PM5/31/20
to Harbour Users

Hi Ash.


On Saturday, 30 May 2020 17:27:09 UTC+3, Ash wrote:
Hello Pete,

Attached is a sample application using GTWVG. It uses ideas from WVWClip. Please compile as shown below.


Hi Ash,
thank you very much for your sample-code. Now, we are making some real progress... ;-)
But, not sure yet if the GUIfication attempt worth the work that I guess is needed to be done.
Ok, I have compiled the code and got the main screen with the menu and the initial controls.
Just what I was looking for! Now I want to proceed, and I tried to implement a simple window,
as you can see in the edited sample which I attach. 
If you have time, look at the "My Window!" item of the menu. The result is not what I expected and hoped to be.
Obviously I did not make it correctly but I don't know how to do it and have no idea (nor some docs) to go further.

Anyway, as I've said in my previous posts, what I try to do  is to create a GUI menu and use it
to call the particular modules as I do now.
I have no intent nor the will nor the energy to edit the (many) screens of the program,
in order to add GUI elements or to "convince" the old textual controls, (say/gets etc),
to try to "live" with with the beauty GTWVG. I really wonder whether is it possible or not?

regards,
Pete
wvgclip.prg

Ash

unread,
May 31, 2020, 2:54:58 PM5/31/20
to Harbour Users
Hello Francesco,

My software is not Multi-Threaded but it is Multi-User. This allows for two workstations to enter invoices at the same time but for different customers. Also, a user can open many instances of my software on his/her workstation and process orders in one, queries in another and reports in the next one; all at the same time. This arrangement has been working well for many years.

Regards.
Ash

Pete

unread,
May 31, 2020, 3:04:25 PM5/31/20
to Harbour Users


On Sunday, 31 May 2020 21:33:35 UTC+3, Pete wrote:

Hi Ash.

On Saturday, 30 May 2020 17:27:09 UTC+3, Ash wrote:
Hello Pete,

Attached is a sample application using GTWVG. It uses ideas from WVWClip. Please compile as shown below.


Hi Ash,
thank you very much for your sample-code. Now, we are making some real progress... ;-)

Newer report! pieces start to get into their place!
Finally I did realize how to control the newly  opened windows.
A good step forward! Well, that's real progress... ;-)

P.S. I just guess that Francesco is talking about MD (multi document) windows.

regards,
Pete

Ash

unread,
May 31, 2020, 3:16:48 PM5/31/20
to Harbour Users
Hello Pete,

Please understand that I am not that familiar with GTWVG. 

Now to your program. Please remove all references to pGT and then try again. 

Regards.
Ash

Steve Litt

unread,
May 31, 2020, 6:17:56 PM5/31/20
to harbou...@googlegroups.com
On Sat, 30 May 2020 17:59:01 +0200
Francesco Perillo <fper...@gmail.com> wrote:

> Pete,
> I invite you to think twice about switching the menu system.
> My program has a very basic, let's say "3270 era" menu system.
> Everytime you make a selection, a new menu opens, nidified. In this
> way users can - from whatever point in the menu system they are, just
> press ESC several times (ESC exits the current menu and control
> returns to the previous) up to the main menu (ESC doesn't working on
> main menu). So, to create an invoice, from any menu they are they can
> press ESC ESC ESC ESC ESC 4 1 1 and the "emit invoice form opens". or
> ESC ESC ESC ESC 6 3 1 to open the form to check if a client have sums
> to pay... I think that forcing them to use mouse may make them lose
> time...

Great minds think alike: http://troubleshooters.com/projects/umenu2/

UMENU2 can work on a teletype terminal, if necessary. And it's all
keyboard all the time.

SteveT

Steve Litt
May 2020 featured book: Troubleshooting Techniques
of the Successful Technologist
http://www.troubleshooters.com/techniques

Steve Litt

unread,
May 31, 2020, 6:27:20 PM5/31/20
to harbou...@googlegroups.com
On Sun, 31 May 2020 11:18:44 -0700 (PDT)
Pete <pete....@gmail.com> wrote:

> Hi Francesco,
>
> On Saturday, 30 May 2020 18:59:08 UTC+3, fperillo wrote:
> >
> > Pete,
> > I invite you to think twice about switching the menu system.
> >
>
> Yes, but I don't want to change the menu. Just to apply some "fresh"
> (read 'window-ish') look onto the already existent.
> Without any other change by now. If it's possible! If it's not, thing
> remain 'as is'.
>
>
> > My program has a very basic, let's say "3270 era" menu system.
> > Everytime you make a selection, a new menu opens, nidified. In this
> > way users can - from whatever point in the menu system they are,
> > just press ESC several times (ESC exits the current menu and
> > control returns to the previous) up to the main menu (ESC doesn't
> > working on main menu).
>
> Oh man! this reminds me some "illustrious" RPG-II days, on an S/36
> IBM system,
> (was beginning of '90s, very young with much zest to learn the
> secrets of these alien beasts).
>
> The problem is that this UI model, while simple and stable, not
> "sells" anymore, mainly because
> the keyboard driven applications are forced to extinction by
> mouse-able and touchable ones.

I don't know anything about GTWVG, but with UMENU2
(http://troubleshooters.com/projects/umenu2/) it would be pretty easy
to make it GUI --- the print statements would be replaced with
something X or whatever X is in Windows. The left click event would
just do what pressing the letter does. UMENU2 even has an Icon property
in the choice structure in case somebody ever does this.

By doing things in this way, people smart enough to save time by using
the keyboard would see no appreciable change in their user interface.
Those with a mental block or wanting to "be modern" can slow themselves
down with the mouse.

Steve Litt

unread,
May 31, 2020, 6:30:44 PM5/31/20
to harbou...@googlegroups.com
On Sun, 31 May 2020 20:29:35 +0200
Francesco Perillo <fper...@gmail.com> wrote:

> Ash, is your software MT? Can you have multiple active windows open
> at the same time?

Wouldn't multiple active open windows be confusing to the user? If the
program is well constructed, there should be very little reason to use
two windows at the same time. And the few times it's helpful, one could
run two copies of the program.

Adalberto Baqueros Cuellar

unread,
May 31, 2020, 7:42:50 PM5/31/20
to Harbour Users
Pete, buenas noches.

Tengo una aplicación  muy antigua actualizada en lo funcional, y ahora adornada con elementos GUI como ser botones, colores y ventanas que simulan ser GUI.

Todo funciona con la eficiencia de antes y ahora con mouse, aunque sigue siendo modo consola.

Si ves conveniente podrías llamarme vía wathsapp y conversar.

Abrazos Adalberto.


Adalberto Baqueros Cuellar

unread,
May 31, 2020, 7:54:05 PM5/31/20
to Harbour Users
Pete, 

Considero que mi deseo de colaborar se verá truncado por el idioma, yo solamente hablo español.

Por favor considera esto.

Abrazos, Adalberto

 

Auge & Ohr

unread,
Jun 1, 2020, 12:15:59 AM6/1/20
to Harbour Users
> Wouldn't multiple active open windows be confusing to the user?
> If the program is well constructed, there should be very little reason to use two windows at the same time.

so MDI Windows are not useful ?

working with GTWVG is OOP not Procedure Code like Cl*pper.

guess you working on Customer "A" and get a Telephone Call from "B".
i will not close "A" under OOP, just Open a new Instance (with Thread) if need

so i depend on Design if MDI make Sense

>And the few times it's helpful, one could run two copies of the program.

it is a Way that i try to avoid ... also under DOS. here my Windows Solution

INIT PROCEDURE
MainInit()
// better than :  SET MULTIPLE OFF WARNING
LOCAL cTitle  
:= 'HBFM ' + cVersion
LOCAL hWndDlg
:= FindWindowEx(,,, cTitle )
   IF
!( hWndDlg == 0 )
     
SetForegroundWindow( hWndDlg )
     
BringWindowToTop( hWndDlg )
     
ShowWindow( hWndDlg, 1 )
     
UpdateWindow( hWndDlg )
      QUIT  
// It is a second instance. Bye Bye
   ENDIF
RETURN

FUNCTION
Main
// here Main begin

since Cl*pper v5.x we can use INIT before MAIN so there i "check" if App is start
under Windows it will switch to App when start 2nd Time and "BringWindowToTop()"

p.s. where can i get latest GTWVG LIB / Source ?

Marek Olszewski "MOL"

unread,
Jun 3, 2020, 8:06:24 AM6/3/20
to Harbour Users
Hi!
Can you help me? I'm trying to compile this sample, but I get linking error:

d:\projekty\testy\wvg>c

d:\projekty\testy\wvg>hbmk2 wvgclip.hbp -comp=mingw
hbmk2: Triggered by #require directive: gtwvg.hbc
hbmk2: Linking... wvgclip.exe
.hbmk/win/mingw/wvgclip.o:wvgclip.c:(.data+0x58): undefined reference to `HB_FUN_WAPI_GETSYSCOLOR'
d:/hb32/lib/libhbvmmt.a(hvmall.o):hvmall.c:(.text+0x11535): undefined reference to `_imp____acrt_iob_func'
d:/hb32/lib/librddcdx.a(dbfcdx1.o):dbfcdx1.c:(.text+0xf80): undefined reference to `_imp____acrt_iob_func'
d:/hb32/lib/librddcdx.a(dbfcdx1.o):dbfcdx1.c:(.text+0x1090): undefined reference to `_imp____acrt_iob_func'
d:/hb32/lib/librddcdx.a(dbfcdx1.o):dbfcdx1.c:(.text+0x134f): undefined reference to `_imp____acrt_iob_func'
d:/hb32/lib/librddcdx.a(dbfcdx1.o):dbfcdx1.c:(.text+0x1467): undefined reference to `_imp____acrt_iob_func'
d:/hb32/lib/librddcdx.a(dbfcdx1.o):dbfcdx1.c:(.text+0x14f4): more undefined references to `_imp____acrt_iob_func' follow
c:/rhomobilesuite6.1/devkit/mingw/bin/../lib/gcc/i686-w64-mingw32/4.7.2/../../../../i686-w64-mingw32/bin/ld.exe: d:/hb32/lib/librddcdx.a(dbfcdx1.o): bad reloc address 0x0 in section `.data'
c:/rhomobilesuite6.1/devkit/mingw/bin/../lib/gcc/i686-w64-mingw32/4.7.2/../../../../i686-w64-mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
hbmk2[wvgclip]: Error: Running linker. 1
gcc.exe .hbmk/win/mingw/wvgclip.o .hbmk/win/mingw/wvgclasses.o .hbmk/win/mingw/_hbmkaut_wvgclip.o    -mwindows -Wl,--start-group -lgtwvg -lxhb -lhbct -lhbtip -lhbfship -lhbxpp -lhbwin -lpng -lhbextern -lhbdebug -lhbvmmt -lhbrtl -lhblang -lhbcpage -lgtcgi -lgtpca -lgtstd -lgtwin -lgtwvt -lgtgui -lhbrdd -lhbuddall -lhbusrrdd -lrddntx -lrddcdx -lrddnsx -lrddfpt -lhbrdd -lhbhsx -lhbsix -lhbmacro -lhbcplr -lhbpp -lhbcommon -lhbmainwin -lwinmm -lkernel32 -luser32 -lgdi32 -ladvapi32 -lws2_32 -liphlpapi -lwinspool -lcomctl32 -lcomdlg32 -lshell32 -luuid -lole32 -loleaut32 -lmpr -lmapi32 -limm32 -lmsimg32 -lwininet -lhbpcre -lhbzlib   -Wl,--end-group -owvgclip.exe  -Ld:/hb32/lib -Ld:/hb32/lib/3rd/win/mingw

hbmk2: Error: Referenced, missing, but unknown function(s): WAPI_GETSYSCOLOR()
How can I resolve this?

W dniu sobota, 30 maja 2020 17:59:08 UTC+2 użytkownik fperillo napisał:
Pete,
I invite you to think twice about switching the menu system.
My program has a very basic, let's say "3270 era" menu system. Everytime you make a selection, a new menu opens, nidified. In this way users can - from whatever point in the menu system they are, just press ESC several times (ESC exits the current menu and control returns to the previous) up to the main menu (ESC doesn't working on main menu).
So, to create an invoice, from any menu they are they can press ESC ESC ESC ESC ESC 4 1 1 and the "emit invoice form opens". or ESC ESC ESC ESC 6 3 1 to open the form to check if a client have sums to pay...
I think that forcing them to use mouse may make them lose time...

What to do when you open a form for creating a invoice? would you disable the menu until the form is closed? Or would you start using MT to have several forms opened (it would be my dream)?


On Thu, May 28, 2020 at 12:27 PM Pete <pete...@gmail.com> wrote:
Hi all,

Any gtwvg power user around here? ;-)

I've been asked to renovate an old (but reliably working) application.
I'm thinking to add some GUI "bells & whistles", starting from a (windows like) GUI Menu.
The rest UI will be remain as is, and gradually in the future I'll, possibly, add, some additional
GUY elements. For now, that's all I want to do. Just a GUI menu.
The question(s) is, is it possible to be done as described and if yes,
has anybody got (and wants to share) a `SIMPLE` sample code, for this thing?
I've looked in `gtwvg\tests` but I found it a little-bit more complicated than I wished it to be.
Any contribution, "as simple as possible and even more simple", is very welcome!

regards,
Pete



--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.

Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbou...@googlegroups.com.

Ash

unread,
Jun 3, 2020, 9:50:33 AM6/3/20
to Harbour Users
Hello Merek,

Need more information about your development environment - Harbour version, MingW version and so on.

Assuming Harbour is installed in c:\hb32, your path should be:

c:\hb32\bin;c:\hb32\comp\mingw\bin

Then compile, as I did

hbmk2 wvgclip.hbp -rebuild

Regards.
Ash

Marek Olszewski "MOL"

unread,
Jun 3, 2020, 11:59:32 AM6/3/20
to Harbour Users
I'm using hb32 newest version from whosaway.com, 32 bit, mingw 10.
I set paths;
I have d:\hb32 and c:\mingw

W dniu środa, 3 czerwca 2020 15:50:33 UTC+2 użytkownik Ash napisał:
Hello Marek,

M., Ronaldo

unread,
Jun 3, 2020, 12:04:25 PM6/3/20
to Harbour Users
HB_FUNC( WAPI_GETSYSCOLOR )
{
   hb_retnint( GetSysColor( hb_parni( 1 ) ) );
}

*This Func is from hb_34

Guillermo Varona Silupú

unread,
Jun 3, 2020, 1:53:40 PM6/3/20
to harbou...@googlegroups.com

Hi

I in my case, added this function (from webpage of Jose Quintas):

#include "hbdyn.ch"
 
// esta funcionou
Function WAPI_GetSysColor( pGetSysColor )
   Local hHandleDll := 0, nColor := 0
   HB_SYMBOL_UNUSED( hHandleDll )
   HB_SYMBOL_UNUSED( nColor )
   hHandleDll := hb_LibLoad("user32.dll")
   nColor := hb_DynCall( { "GetSysColor", hHandleDll, HB_DYN_CALLCONV_STDCALL }, pGetSysColor ); HB_SYMBOL_UNUSED( nColor )
   hb_LibFree( hHandleDll )
   Return nColor

I hope this helps.

BR

GVARONAS


Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/harbour-users/e72253dc-1e08-40d7-a7ed-e778ef114da5%40googlegroups.com.

Ash

unread,
Jun 3, 2020, 6:28:58 PM6/3/20
to Harbour Users
Hello Merek,

May I suggest that you download nightly Harbour binaries. It comes with a version of MingW. Install Harbour in c:\hb32 folder and try again.


Regards.
Ash

Marek Olszewski "MOL"

unread,
Jun 4, 2020, 2:07:15 AM6/4/20
to Harbour Users
It's working now!
Thank you!
Message has been deleted

Pete

unread,
Jun 4, 2020, 3:01:20 AM6/4/20
to Harbour Users

Hi all,
(couldn't contribute to thread the few past days, due to lack of time)

I think the initial request for a GTWVG menu has been completed, more or less, successfully!
A general impression is that GTWVG can be a quite good candidate  library for use, to apply `GUIfication` on legacy textual UI appls.
(Ok, my conclusion may be a little belated, given the GTVWG library is here for several years now, but now I had the chance to to look into it).
The only `stopper` for someone to exploit the capabilities of GTWVG is not the "usual suspect", the documentation, :-)
but, IMO, the lack of small compile-able samples, displaying the functionality of different GUI elements and functions of the library.
Anyway I do upload here a reworked sample menu, in the hope it could be useful and in the hope it may expanded even more
and re-uploaded  back as a more useful module.
I think there remain things to be addressed but the base sample can be a good starting point for further experiment.

Many thanks  to all, particularly to Ash for his kind offer of the initial sample and always to Pritpal, author of the GTWVG.

regards,
Pete
WVGMenu(src).7z

Pete

unread,
Jun 4, 2020, 3:36:52 AM6/4/20
to Harbour Users


On Thursday, 4 June 2020 10:01:20 UTC+3, Pete wrote:
The only `stopper` for someone to exploit the capabilities of GTWVG is not the "usual suspect", the documentation, :-)
but, IMO, the lack of small compile-able samples, displaying the functionality of different GUI elements and functions of the library.

ADDENDUM:
I had in mind to post a link of a page that includes some interesting GTWVG samples, but forgot to write it.
So, here it is: http://www.elektrosoft.it/tutorials/gtwvg/gtwvg.asp
by our fellow Giovanni Di Maria, who has created and other Harbour docs. Thanks!

regards,
Pete

 

CCH4CLIPPER

unread,
Jan 31, 2022, 12:52:16 AM1/31/22
to Harbour Users
Hi Pete

This is exactly what I am looking for as other than a windows menuing system, already using gtwvg fruitfulli for a large legacy Clipper application.

Thanks

CCH4CLIPPER 

Chee Chong Hwa

unread,
Jan 31, 2022, 9:38:32 PM1/31/22
to harbou...@googlegroups.com
Hi All

With the help of this thread, have successfully added Windows-like menu to my legacy Harbour 3.2+WVG project.
Need to just go a little bit further. Has anyone added sub-menus ? Would appreciate any help here via code fragments or simple compilable prg

TIA

CCH4CLIPPER

--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.

Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/harbour-users/e1cfba4e-cc9c-486d-b30f-f2a1db533bedn%40googlegroups.com.

José M. C. Quintas

unread,
Feb 1, 2022, 9:23:37 AM2/1/22
to harbou...@googlegroups.com

My menu is an array.

I do not like windows menu, but can use it.


STATIC FUNCTION MenuWvg( mMenuOpt )

   LOCAL oMenu, nKey

   oMenu  := wvgSetAppWindow():MenuBar()
   BuildMenu( oMenu, mMenuOpt )
   DO WHILE .T.
      nKey := Inkey( INKEY_IDLE )
      DO CASE
      CASE nKey == HB_K_GOTFOCUS
      CASE nKey == HB_K_LOSTFOCUS
      CASE nKey == K_ESC
         EXIT
      ENDCASE
   ENDDO
   wvgSetAppWindow():oMenu := NIL
   wapi_SetMenu( wapi_GetActiveWindow(), NIL )
   wapi_DestroyMenu( oMenu:hWnd )

   RETURN NIL

FUNCTION BuildMenu( oMenu, acMenu )

   LOCAL oElement, oSubMenu, cbCode, m_ProgTxt

   FOR EACH oElement IN acMenu
      IF Len( oElement[ 2 ] ) == 0
         m_Prog := oElement[ 3 ]
         IF ValType( m_Prog ) == "C"
            m_ProgTxt := AppEmpresaApelido() + " (" + AppUserName() + ") (" + m_Prog + ") " + Upper( oElement[ 1 ] )
            cbCode     := [{ || RunModule( "] + m_Prog + [", "] + m_ProgTxt + [" ) }]
            oMenu:AddItem( oElement[ 1 ] , &( cbCode ) )
         ELSE
            oMenu:AddItem( oElement[ 1 ], oElement[ 3 ] )
         ENDIF
      ELSE
         oSubMenu := WvgMenu():new( oMenu, , .T. ):Create()
         BuildMenu( oSubMenu, oElement[ 2 ] )
         oMenu:AddItem( oSubMenu, oElement[ 1 ] )
      ENDIF
   NEXT

   RETURN NIL

For array creation:

   nMenuLevel   := 0
   oMenuOptions := {}

   MenuOption( "Faturamento" )
      MenuDrop()
      MenuOption( "Pedidos/Notas/Manifesto" )
         MenuDrop()
         MenuOption( "Orçamentos/Pedidos",                   "PJPPEDIDO" )
         MenuOption( "Orçamentos/Pedidos SubOpções" )
            MenuDrop()
            MenuOption( "(I)Ped.Cancelamento",               "ADMPEDCAN" )
            MenuOption( "(I)Reemite Cupom pra Pedido",       "PJPPEDIDOCUPOM" )
            MenuOption( "(I)Ped.Duplicar Pedidos",           "ADMPEDCLO" )

           MenuUndrop()

   MenuUndrop()

MenuUnDrop()

//

STATIC FUNCTION MenuOption( cCaption, cModule, bCode )

   LOCAL nCont, oLastMenu

   oLastMenu := oMenuOptions
   FOR nCont = 1 TO nMenuLevel
      oLastMenu := oLastMenu[ Len( oLastMenu ) ]
      oLastMenu := oLastMenu[ 2 ]
   NEXT
   AAdd( oLastMenu, { cCaption, {}, cModule, bCode, 1 } )

   RETURN NIL

STATIC FUNCTION MenuDrop()

   nMenuLevel++

   RETURN NIL

STATIC FUNCTION MenuUnDrop()

   nMenuLevel--

   RETURN NIL

José M. C. Quintas

CCH4CLIPPER

unread,
Feb 1, 2022, 10:09:32 PM2/1/22
to Harbour Users
Hi Jose

TQVM for responding :-)

Is it possible for you to attach a compileable prg for me to study ?

TIA

CCH4CLIPPER

José M. C. Quintas

unread,
Feb 3, 2022, 8:06:29 AM2/3/22
to harbou...@googlegroups.com

Same code I already send.

José M. C. Quintas

test.prg

CCH4CLIPPER

unread,
Feb 4, 2022, 4:42:24 AM2/4/22
to Harbour Users
Hi Nick

Very nice :-)

Thank you !

Chee Chong Hwa

unread,
Feb 4, 2022, 10:45:47 AM2/4/22
to harbou...@googlegroups.com
Hi Jose

Very nice :-)

Thank you !

Jorge Garate

unread,
Dec 1, 2022, 11:14:29 AM12/1/22
to Harbour Users

Hello:

in my case I have some .prg in Windows mode, but I start the application in console mode :-( which runs programs in .prg Windows mode (GUI) 

  ...and what I tried many times is to start the menu in Windows mode and have it load .prg in console mode, which it did but lost FOCUS and the user had to find the window that was not active to work on it.

***************************
Hola:
 en mi caso tengo unos .prg en modo Windows, pero inicio la aplicación en modo consola :-(   que ejecuta programas en .prg modo Windows (GUI)  

...y lo que intenté muchas veces es iniciar el menú en modo Windows y que cargara .prg en modo consola, que sí lo hacía pero  perdía el FOCO y el usuario debía buscar la ventana que no estaba activa para trabajar en ella. 

***************************


Jorge

José M. C. Quintas

unread,
Dec 1, 2022, 11:29:55 AM12/1/22
to harbou...@googlegroups.com

On tests I mix GTWVG with HWGUI, HMG, HMG Extended, OOHG.

I do not have console module, use GTWVG for all.

I use multithread, then each module have it's own thread, and more than one module can be opened at same time, including the same.

Console uses the Windows console, I think it is not a good option to mix.

José M. C. Quintas


---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.

Jorge Garate

unread,
Dec 1, 2022, 11:44:50 AM12/1/22
to Harbour Users
Hello Jose:

By "console mode" I mean GTWVG

FUNCTION Main()
LOCAL lReadParam := .T.
PUBLIC pcCompanyName, pcCompanyRut, ;
pnMonthInProcess, pcYearInProcess, pnYearInProcess, ;
pcDirEmpresa, pcComEmpresa, pcCiuEmpresa, pcFonEmpresa, pcGirEmpresa, ;
pcDirContab, pcDirAuxDoc, pcDirAuxPro, pcDirAuxCli, ;
pcUserName, pcComputerName, pcPathTemp, ;
pcLgoDocClie, pcLgoDocProv, pcLgoCorClie, pcLgoCorProv, pcLgoCorDoc, pcPictCodCta

ANNOUNCE HB_GT_SYS
REQUEST HB_GT_WIN_DEFAULT
SetMode(25,80) 

// disable window X button
hb_gtInfo( HB_GTI_CLOSABLE, .F. )

REQUEST HB_LANG_ES
HB_LANGSELECT( "ES" )
SET LANGUAGE TO SPANISH //Select language for message interface

**** START MENU ****


José M. C. Quintas

unread,
Dec 1, 2022, 11:53:37 AM12/1/22
to harbou...@googlegroups.com

Using REQUEST HB_GT_WIN_DEFAULT, you are using console, not GTWVG.

Change to REQUEST HB_GT_WVG_DEFAULT

Note: when using GUI/GTWVG, may be you need a new errorsys, I change it to write to HB_OUT.LOG and open on notepad.

José M. C. Quintas

José M. C. Quintas

unread,
Dec 1, 2022, 12:00:33 PM12/1/22
to harbou...@googlegroups.com

my mistake:

REQUEST HB_GTWVG_DEFAULT

José M. C. Quintas



-------- Mensagem encaminhada --------
Assunto: Re: [harbour-users] Re: simple GTWVG sample code?
Data: Thu, 1 Dec 2022 13:53:31 -0300
De:
José M. C. Quintas <jmcqu...@gmail.com>

Jorge Garate

unread,
Dec 1, 2022, 2:15:38 PM12/1/22
to Harbour Users
Gracias, probaré con tu sugerencia.

HBQuerier

unread,
Sep 8, 2023, 8:38:54 PM9/8/23
to Harbour Users
Hi Pritpal,

I don't know if you're still around, but I tried commenting all of this lines, and harbour then gives me warnings about missing assignments and such (variable is declared but not assigned/used), and it doesn't compile.

Do you mean to comment out ALL of the lines you mentioned?  I tried that.

I want to try and build the demo with only text-mode components, if that's possible.

On Thursday, May 28, 2020 at 8:47:59 AM UTC-4 Pritpal Bedi wrote:
Hi Pete

Just remove or comment-out these lines from demowvg.prg. and you will get a pure console window without GETs GUIed.



   oLastMenu:disableItem( 11 )
   oLastMenu:checkItem( 1 )
   oLastMenu:insItem( 11, { "I am inserted later !", ;
      {|| wvg_MessageBox( , "Hi " + iif( oLastMenu:isItemChecked( 1 ), "Yes", "No" ) + ;
      iif( oLastMenu:isItemEnabled( 12 ), " Yes", " No" ) ) } } )

   oLastMenu:setItem( 14, { "This is Set Against Prev Menu", {|| wvg_MessageBox( , "Hi" ) } } )

   SetMode( MaxRow() + 1, MaxCol() + 1 )  /* Needed to accommodate attached menu */

   SetKey( K_F12        , {|| hb_gtInfo( HB_GTI_ACTIVATESELECTCOPY ) } )
   SetKey( K_CTRL_V     , {|| __Keyboard( hb_gtInfo( HB_GTI_CLIPBOARDDATA ) ) } )
   SetKey( K_RBUTTONDOWN, {|| __Keyboard( hb_gtInfo( HB_GTI_CLIPBOARDDATA ) ) } )

   hPopup := wvt_SetPopupMenu()

   pGT := SetGT( 1, hb_gtSelect() )

   /* Force mouse pointer right below the Harbour label */
   wvt_SetMousePos( 2, 40 )

   AAdd( aBlocks, {|| wvt_SetIcon( GetResource( "vr_1.ico" ) ) } )
   AAdd( aBlocks, {|| Wvt_SetTitle( "Vouch" ) } )
   AAdd( aBlocks, {|| wvt_DrawLabel( 1, 40, cLabel, 6,, RGB( 255, 255, 255 ), RGB( 198, 198, 198 ), "Arial", 26, , , , , .T., .T. ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxRaised( nTop, nLft, nBtm, nRgt ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxRecessed( 7, 61, 13, 70 ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxGroup( 15, 59, 18, 72 ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxGroup( 5, 6, 19, 44 ) } )
   AAdd( aBlocks, {|| wvt_DrawImage( 8, 62, 12, 69, IMAGE_VOUCH, , .T. ) } )
   AAdd( aBlocks, {|| wvt_DrawBoxRecessed( 7, 48, 13, 55 ) } )
   AAdd( aBlocks, {|| wvt_DrawLine( MaxRow() - 2, 0, MaxRow() - 2, MaxCol(), WVT_LINE_HORZ, WVT_LINE_RECESSED, WVT_LINE_BOTTOM ) } )
   AAdd( aBlocks, {|| wvt_DrawLine( MaxRow() - 1, 41, MaxRow(), 41, WVT_LINE_VERT, WVT_LINE_RECESSED, WVT_LINE_CENTER ) } )
   AAdd( aBlocks, {|| AEval( GetList, {| oGet | wvt_DrawBoxGet( oGet:Row, oGet:Col, Len( Transform( oGet:VarGet(), oGet:Picture ) ) ) } ) } )

   AAdd( aBlocks, {|| wvt_Mouse( -1000001 ) } )

   aLastPaint := WvtSetBlocks( aBlocks )

   /* Xbase++ compatible pure GUI controls onto CUI console */
   BuildButtons()


It is as simple as that. GUI controls are glued on top of pure character interface. You need not to if so desired.


Pritpal Bedi
a student of software analysis & concepts

Martin Fears

unread,
Jul 8, 2025, 6:49:00 PMJul 8
to Harbour Users
Appreciate this thread has been inactive for almost 2 years now, but ....
Having recently Harbour-ised my 1995 Cl*pper app, I'm now just starting the journey to GUI-ify it.

I've been reading various threads, discussing the pros & cons for the various ways this might be achieved and have elected to go down the WVG route.
I intended my app to remain fully modal to simplify the transition and retain screen-flow interaction.

The "menu" conversation above is very helpful as this is where I will start.
I've adopted some of @Pritpal Bedi code ie FUNCTION BuildMainMenu() with some success.
But I did not see a response to @Chee Chong Hwa question about how to generate sub-menus.
See picture attached (Capture.JPG) of example sub-menu from Notepad.
Please can someone explain what I need to do - some simple code would be ideal.

I note that many of the WVG functions start "Wvt ....." - where can I find help on all the WVG functions, including: Syntax, Arguments, Returns, Description & Examples - like I can find here
If someone can point me to where I can find something like this (Google has failed me so far), I'd be very grateful.

Any other hints and tips on a simple Console to GUI facelift - not planning on anything too wizzy - I'm looking at you @Pete

I'm a part-time coder so please keep it as simple as possible.
Example PRG & HBP very much appreciated as although I'm quite fluent in Cl*pper, I've only started Harbour 6 months ago.

Thanks in anticipation ....

Martin
Capture.JPG

José M. C. Quintas

unread,
Jul 8, 2025, 7:02:59 PMJul 8
to harbou...@googlegroups.com

Submenu is the same as menu.

You create a menu and add as an option on another menu.

My primary use is gtwvg with multithread, together with hwgui and fivewin, on same EXE.

Look this, creating menu from array with any level.

   oMenu  := wvgSetAppWindow():MenuBar()
   BuildMenu( oMenu, mMenuOpt )

FUNCTION BuildMenu( oMenu, acMenu )

   LOCAL oElement, oSubMenu, cbCode, xFrmNameTxt



   FOR EACH oElement IN acMenu
      IF Len( oElement[ 2 ] ) == 0

            oMenu:AddItem( oElement[ 1 ], oElement[ 3 ] ) // here add a single option
      ELSE
         oSubMenu := WvgMenu():new( oMenu, , .T. ):Create() // here create the submenu


         BuildMenu( oSubMenu, oElement[ 2 ] )

         oMenu:AddItem( oSubMenu, oElement[ 1 ] ) // here add submenu as an option
      ENDIF
   NEXT

   RETURN NIL

--
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: https://groups.google.com/group/harbour-users
---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.

Martin Fears

unread,
Oct 29, 2025, 8:13:35 AM (yesterday) Oct 29
to Harbour Users
Hi Jose

Please can you provide example(s) of acMenu to work with above.

Ideally to include sub-menu and the "-" aka oMenu:AddItem( "-" )

Many thanks

Martin

José M. C. Quintas

unread,
Oct 29, 2025, 5:28:00 PM (yesterday) Oct 29
to harbou...@googlegroups.com

I use a traditional menu creation, may be gtwvg, hwgui, fivewin, minigui.

Use same style on Visual Basic 6 a long time ago.

As an array, it is easy to add or remove options, and setup for each user/password.


MEMVAR xFrmName, nMenuLevel, oMenuOptions

FUNCTION MenuCria()

   PRIVATE nMenuLevel, oMenuOptions

   hb_Default( @lInterno, .T. )


   nMenuLevel   := 0
   oMenuOptions := {}

   MenuOption( "Faturamento" )
      MenuDrop()
      MenuOption( "Pedidos/Notas/Manifesto" )
         MenuDrop()
         MenuOption( "Orçamentos/Pedidos",                   "PJPPEDIDO" )

         MenuOption( "-", "-" ) // separator



         MenuOption( "Orçamentos/Pedidos SubOpções" )
            MenuDrop()
            MenuOption( "(I)Ped.Cancelamento",               "ADMPEDCAN" )

          MenuOption( "Any codeblock", { || Nil } )
            MenuUndrop()

      MenuUnDrop()

   RETURN oMenuOptions


STATIC FUNCTION MenuOption( cCaption, cModule, bCode )

   LOCAL nCont, oLastMenu

   oLastMenu := oMenuOptions
   FOR nCont = 1 TO nMenuLevel
      oLastMenu := oLastMenu[ Len( oLastMenu ) ]
      oLastMenu := oLastMenu[ 2 ]
   NEXT
   AAdd( oLastMenu, { cCaption, {}, cModule, bCode, 1 } )

   RETURN NIL

STATIC FUNCTION MenuDrop()

   nMenuLevel++

   RETURN NIL

STATIC FUNCTION MenuUnDrop()

   nMenuLevel--

   RETURN NIL


FUNCTION MenuWvg( mMenuOpt )

   LOCAL oMenu, nKey

   oMenu  := wvgSetAppWindow():MenuBar()
   BuildMenu( oMenu, mMenuOpt )

   DO WHILE .T.
      nKey := Inkey( INKEY_IDLE )
      DO CASE
      CASE nKey == HB_K_GOTFOCUS
      CASE nKey == HB_K_LOSTFOCUS
      CASE nKey == K_ESC
         EXIT
      ENDCASE
   ENDDO
   wvgSetAppWindow():oMenu := NIL
   wapi_SetMenu( wapi_GetActiveWindow(), NIL )
   wapi_DestroyMenu( oMenu:hWnd )

   RETURN NIL

FUNCTION BuildMenu( oMenu, acMenu )

   LOCAL oElement, oSubMenu, cbCode, xFrmNameTxt

   FOR EACH oElement IN acMenu
      IF Len( oElement[ 2 ] ) == 0

         xFrmName := oElement[ 3 ]
         IF ValType( xFrmName ) == "C"
            xFrmNameTxt := AppEmpresaApelido() + " (" + AppUserName() + ") (" + xFrmName + ") " + Upper( oElement[ 1 ] )
            cbCode     := [{ || RunModule( "] + xFrmName + [", "] + xFrmNameTxt + [" ) }]


            oMenu:AddItem( oElement[ 1 ] , &( cbCode ) )
         ELSE

            oMenu:AddItem( oElement[ 1 ], oElement[ 3 ] ) // codeblock
         ENDIF


      ELSE
         oSubMenu := WvgMenu():new( oMenu, , .T. ):Create()

         BuildMenu( oSubMenu, oElement[ 2 ] )
         oMenu:AddItem( oSubMenu, oElement[ 1 ] )

      ENDIF
   NEXT

   RETURN NIL



José M. C. Quintas

Martin Fears

unread,
Oct 29, 2025, 7:38:37 PM (yesterday) Oct 29
to Harbour Users
Thanks, but I don't see the array contents - I see "acMenu" but I don't see an example of what acMenu looks like??

I've tried building it:
AADD( acMenu , { "cItem" , "cSubMenu , bCodeBlock  } )
etc. etc. for the entire menu ....
Does your code support the entire menu creation in one single acMenu or do I have to build the menu up one "Caption" at a time?

I've attempted to do it as one array by inserting a new element at the front:
AADD( acMenu , { "cCaption" , "cItem" , "cSubMenu , bCodeBlock  } )
and changing your code slightly to look at the different oElement[ n+1 ]
This works fine for all the normal Menu items, but fails on the Sub-menu elements

Here is my acMenu creation:
FUNCTION MainMenuArray()
LOCAL aMenu := {}

IF !L_PRODUCTION
   AADD( aMenu , { "DEVELOPER" , "MF Test Func"            , ""            , {|| Test()                  } } )
   AADD( aMenu , { "DEVELOPER" , "-"                       , ""            ,                               } )
   AADD( aMenu , { "DEVELOPER" , "Refresh MVP Points"      , ""            , {|| RefreshMVP( "MENU" )    } } )
   AADD( aMenu , { "DEVELOPER" , "Switch Shareware"        , ""            , {|| SwitchShareware()       } } )
ENDIF

AADD( aMenu , { "Matches" , "View Match"                   , ""            , {|| SelectFixture("VIEW")   } } )
IF CCA_ADMIN
   AADD( aMenu , { "Matches" , "-"                         , ""            ,                               } )
   AADD( aMenu , { "Matches" , "Add New Match"             , ""            , {|| EnterAnalysis("NEW")    } } )
   AADD( aMenu , { "Matches" , "Import Match"              , ""            , {|| EnterAnalysis("IMPORT") } } )
   AADD( aMenu , { "Matches" , "Edit Match"                , ""            , {|| SelectFixture("EDIT")   } } )
ENDIF

AADD( aMenu , { "Analysis" , "Cumulative"                  , "Individual"  , {|| Averages("CI")          } } )
AADD( aMenu , { "Analysis" , "Seasonal"                    , "Individual"  , {|| Averages("SI")          } } )
AADD( aMenu , { "Analysis" , "Captaincy & Toss"            , "Individual"  , {|| Averages("CAPTAIN")     } } )
AADD( aMenu , { "Analysis" , "Appearances"                 , "Individual"  , {|| Averages("A")           } } )
AADD( aMenu , { "Analysis" , "Cumulative"                  , "Team"        , {|| Averages("T")           } } )
AADD( aMenu , { "Analysis" , "Seasonal"                    , "Team"        , {|| Averages("ST")          } } )
AADD( aMenu , { "Analysis" , "All Records"                 , "Team"        , {|| Averages("E")           } } )
AADD( aMenu , { "Analysis" , "Player Form"                 , ""            , {|| Averages("FORM")        } } )
AADD( aMenu , { "Analysis" , "Player Selection"            , ""            , {|| Averages("PS")          } } )
AADD( aMenu , { "Analysis" , "Player Retention"            , ""            , {|| Averages("PR")          } } )

AADD( aMenu , { "Data Files" , "Players"                   , ""            , {|| VariBrowse("PLAYERS")   } } )
AADD( aMenu , { "Data Files" , "Opponents"                 , ""            , {|| VariBrowse("OPPONENTS") } } )
AADD( aMenu , { "Data Files" , "Team Types"                , ""            , {|| VariBrowse("TEAMTYPE")  } } )

IF CCA_ADMIN
   AADD( aMenu , { "Maintenance" , "Merge Player Records"  , ""            , {|| MergePlayer()           } } )
   AADD( aMenu , { "Maintenance" , "Re-Index Files"        , ""            , {|| ReindexFiles("FUNC")    } } )
   AADD( aMenu , { "Maintenance" , "Pack Files"            , ""            , {|| ReindexFiles("PACK")    } } )
   AADD( aMenu , { "Maintenance" , "Cumulative Validation" , ""            , {|| SumCheck("MENU")        } } )
ENDIF
AADD( aMenu , { "Maintenance"    , "Membership Check"      , "Memberships" , {|| MembershipCheck()       } } )
IF CCA_ADMIN
   AADD( aMenu , { "Maintenance" , "Reset Memberships"     , "Memberships" , {|| ResetMemberships()      } } )
ENDIF

AADD( aMenu , { "Other" , "Quit"                           , ""            , {|| CCAExit()               } } )
IF CCA_ADMIN
   AADD( aMenu , { "Other" , "Set Junior Age"              , ""            , {|| SetJuniorAge()          } } )
   AADD( aMenu , { "Other" , "Set Score Format"            , ""            , {|| SetScoreFormat()        } } )
   AADD( aMenu , { "Other" , "Set Season Break"            , ""            , {|| SetSplitYear()          } } )
   IF .T. // control->shareware
      AADD( aMenu , { "Other" , "Register"                 , ""            , {|| RegisterCCA()           } } )
   ELSE
      AADD( aMenu , { "Other" , "Check for Update"         , ""            , {|| CheckForAppUpdate()     } } )
      AADD( aMenu , { "Other" , "Test Print"               , ""            , {|| Print("TEST")           } } )
   ENDIF
ENDIF
AADD( aMenu , { "Other" , "User Guide"                     , ""            , {|| Help("MANUAL")          } } )
AADD( aMenu , { "Other" , "About " + CCA_SHORT_NAME        , ""            , {|| About()                 } } )

RETURN aMenu

and here is my code to build the menu from this array:
FUNCTION GUIBuildMenu( acMenu )
LOCAL oMenuBar := wvgSetAppWindow():MenuBar(),oMenu,oSubMenu
LOCAL aElement,cGroup := " ",cCaption,cSubMenu,lSubMenu := .F.

FOR EACH aElement IN acMenu
   IF aElement[1] + aElement[3] != cGroup
      IF lSubMenu
         IF !EMPTY( oSubMenu )                  // don't "add" first time round
            oMenu:addItem( { oSubMenu , cSubMenu } )
         ENDIF
      ELSE
         IF !EMPTY( oMenu )                     // don't "add" first time round
            oMenuBar:addItem( { oMenu , cCaption } )
         ENDIF
      ENDIF
      lSubMenu := IIF( LEN( aElement[3] ) == 0 , .F. , .T. )
      cSubMenu := aElement[3]
      cGroup   := aElement[1] + aElement[3]       // make a unique key to identify next menu item
      IF cCaption != aElement[1]
         cCaption := aElement[1]
         oMenu := wvgMenu():new( oMenuBar , , .T. ):create()
         oMenu:Caption := cCaption
      ENDIF
      IF lSubMenu
         oSubMenu := wvgMenu():new( oMenuBar , , .T. ):create()
         oSubMenu:Caption := cSubMenu  //Caption
      ENDIF
   ENDIF

   IF lSubMenu
      oSubMenu:AddItem( oSubMenu, aElement[2] )           // add submenus
   ELSE
      oMenu:AddItem( aElement[2], aElement[4] )           // add a single menu
   ENDIF
NEXT
IF lSubMenu                                               // capture the last one on exit
   oMenu:addItem( { oSubMenu , cSubMenu } )
ENDIF
oMenuBar:addItem( { oMenu , cCaption } )

RETURN NIL
 Hopefully you can see I'm trying to build a re-use generic menu creator that will work with variety of acMenu(s) as required

Any ideas?

Many thanks

Martin

José M. C. Quintas

unread,
9:12 AM (11 hours ago) 9:12 AM
to harbou...@googlegroups.com

It is ready to use, why create another?

I use it for traditional or GUI

{ "name of the option", {}, "module", { || block() }, 1 }

Submenu is added to second option, unlimited level

What is the problem on doing this:

IF !L_PRODUCTION
   MenuOption( "Developer" )
      MenuDrop()
      MenuOption( "MF Test Func", { || Test() } )


      MenuOption( "-", "-" )

      MenuOption( "Refresh MVP Points",{|| RefreshMVP( "MENU" ) } )
      MenuOption( "Switch Shareware", {|| SwitchShareware()       } )
      MenuUnDrop()
ENDIF
MenuOption( "Matches" )
   MenuDrop()
   MenuOption( "View Match", {|| SelectFixture("VIEW")   } )
   IF CCA_ADMIN
      MenuOption( "Add New Match", {|| EnterAnalysis("NEW")    } )
      MenuOption( "Import Match", {|| EnterAnalysis("IMPORT") } )
      MenuOption( "Edit Match", {|| SelectFixture("EDIT")   } )
   ENDIF
   MenuUnDrop()
MenuOption( "Analysis" )
   MenuDrop()   
   MenuOption( "Cumulative Individual"  , {|| Averages("CI")          } )
   MenuOption( "Seasonal Individual"  ,  {|| Averages("SI")          } )
   MenuOption( "Captaincy & Toss Individual"  , {|| Averages("CAPTAIN")     } )
   MenuOption( "Appearances Individual"  , {|| Averages("A")           } )
   MenuOption( "Cumulative Team"        , {|| Averages("T")           } )
   MenuOption( "Seasonal Team"        , {|| Averages("ST")          } )
   MenuOption( "All Records Team"        , {|| Averages("E")           } )
   MenuOption( "Player Form", {|| Averages("FORM")        } )
   MenuOption( "Player Selection", {|| Averages("PS")          } )
   MenuOption( "Player Retention", {|| Averages("PR")          } )
   MenuUnDrop()
MenuOption( "Data Files" )
   MenuDrop()
   MenuOption( "Players", {|| VariBrowse("PLAYERS")   } )
   MenuOption( "Opponents", {|| VariBrowse("OPPONENTS") } )
   MenuOption( "Team Types", {|| VariBrowse("TEAMTYPE")  } )
   MenuUnDrop()
MenuOption( "Maintenance" )
   MenuDrop()
   IF CCA_ADMIN
      MenuOption( "Merge Player Records"  , {|| MergePlayer() } )
      MenuOption( "Re-Index Files"        , {|| ReindexFiles("FUNC") } )
      MenuOption( "Pack Files", {|| ReindexFiles("PACK") } )
      MenuOption( "Cumulative Validation" , {|| SumCheck("MENU") } )
  ENDIF
  MenuOption( "Membership Check", {|| MembershipCheck() } )
   IF CCA_ADMIN
      MenuOption( "Reset Memberships", {|| ResetMemberships() } )
   ENDIF   
   MenuUndrop()
MenuOption( "Other" )
   MenuDrop()   
   MenuOption( "Quit", {|| CCAExit() } )
   IF CCA_ADMIN
      MenuOption( "Set Junior Age", {|| SetJuniorAge() } )
      MenuOption( "Set Score Format", {|| SetScoreFormat() } )
      MenuOption( "Set Season Break", {|| SetSplitYear() } )


      IF .T. // control->shareware

         MenuOption( "Register", {|| RegisterCCA() } )
      ELSE
         MenuOption( "Check for Update", {|| CheckForAppUpdate() } )
         MenuOption( "Test Print", {|| Print("TEST") } )
      ENDIF
   ENDIF
   MenuOption( "User Guide", {|| Help("MANUAL") } )
   MenuOption( "About " + CCA_SHORT_NAME, {|| About() } )
   MenuUndrop()
   

José M. C. Quintas

Martin Fears

unread,
2:03 PM (6 hours ago) 2:03 PM
to Harbour Users
MenuDrop() & MenuUnDrop() are new functions to me ...
Can you point me to where I can find help on all the GTWVG functions and their parameters?
Many thanks ...

José M. C. Quintas

unread,
6:58 PM (1 hour ago) 6:58 PM
to harbou...@googlegroups.com

I send all source code with them on previous emails.

MenuOption() allways add on array of current level.

MenuDrop() and MenuUndrop() moves the level up/down.

They are not part of WVG.

Adjust all these functions for your needs


José M. C. Quintas

Reply all
Reply to author
Forward
0 new messages