curly
Full Member
Posts: 161
|
Post by curly on Nov 24, 2021 12:15:01 GMT -5
Brandon, Firstly, if I grab a screen image with Alt+PrtSc, I can paste it into the this text area? What about photos? Kind regards, David
|
|
|
Post by Carl Gundel on Nov 24, 2021 13:08:38 GMT -5
The giant range of knowledge, skill, and talent that I have dealt with over decades from users of Liberty BASIC and from people trying be users is staggering. Some people have no hope of ever getting it to do anything for them (yes, really), and some people are smarter than I am, and everything in between.
Unless someone is obviously making trouble, or is hostile, we need to meter out patience and benefit of the doubt.
My two cents.
|
|
|
Post by Rod on Nov 24, 2021 15:21:00 GMT -5
This is not criticism just comment. 9000 lines is too much. API is not BASIC. David is a beginner. So if we MUST use API we should keep it focused, as simple as it can be and addressing the current problem.
Walt, I think you forget how much knowledge you have acquired over the years and how easily API code comes to your fingertips. You are an asset and a prized contributor.
David, in a years time you will want to simplify and rewrite everything you have just coded. You could probably manage it in 1000 lines.
You have described the project well enough but your GUI is sketchy. So we struggle to understand what is the best solution. At 9000 lines it has to be a hotch potch of code, if it works great but as you stumble on bugs and quirks solutions will become harder.
However it is your project and however you complete it is down to you.
The menu can be removed completely. It is not difficult to do. Show us the code you use to remove the menu. Answer the questions asked. Walt asked if you created the menus yourself with API or whether it was created automatically because you included a texteditor control. So did you open a texteditor?
|
|
|
Post by Rod on Nov 24, 2021 15:25:31 GMT -5
You cannot post screen images directly to this forum. You need a host like Dropbox or a file sharing web resource. Google it.
|
|
|
Post by Brandon Parker on Nov 24, 2021 16:28:52 GMT -5
Brandon, Firstly, if I grab a screen image with Alt+PrtSc, I can paste it into the this text area? What about photos? Kind regards, David You can upload a file as an attachment; just keep the size fairly small. The forum has an allotment that is not that large. If your version of Windows has the Snipping tool, use that. Save the image to your computer, and then upload it here. {:0) Brandon Parker
|
|
curly
Full Member
Posts: 161
|
Post by curly on Nov 25, 2021 12:08:16 GMT -5
Carl, thank you for your kind words,
Brandon, Rod, Walt and Metro,
I have windows 10, and someone mentioned a snipping tool, so I assume I have it. I'll find out how to use it. I have a Dropbox account, but can't find any way to share files with you other than email? Is there another way? I have taken a screen shot as a jpg of my #home window ready to share. I
I hope this description is clear? My home window is a plain window, #home. I have a narrow graphicbox that runs almost the full width of #main window. I have printed a string inside the graphicbox containing my menu items, and use mouse position in the graphic box to select my menu item. Control jumps to the [label] associated with the menu item (relevant mouse position). I also have a hidden ListBox that deviations are printed to as they are identified, and displayed to the user when validation is finished. The user has a button to select all and copy to a hidden texteditor where they are then automatically copied to the windows clipboard. I assume this texteditor is why my little Edit menu appears?
The code I have to make it look as if the menu doesn't exist came from Alyce's Restaurant, menugone, and is adapted as follows:-
This runs as soon as #home is opened
Menu #home, "","",[quit.home] 'This jumps to my 'Are you sure to want to shut down' routine if the menu item is clicked Menu #home, "Edit" hMain=hWnd(#home) hMainMenu=GetMenu(hMain) hMainEdit=GetSubMenu(hMainMenu,1) result=RemoveMenu(hMainMenu,hMainEdit) Call DrawMenuBar hWnd(#home)
This is the sub and the functions Sub DrawMenuBar hWnd CallDLL #user32, "DrawMenuBar",_ hWnd As ulong, r As boolean End Sub
Function GetSubMenu(hMenuBar,nPos) CallDLL #user32, "GetSubMenu",_ hMenuBar As ulong, nPos As long,_ GetSubMenu As ulong End Function
Function GetMenu(hWnd) CallDLL #user32, "GetMenu",hWnd As ulong,_ GetMenu As ulong End Function
Function RemoveMenu(hMenu,hSubMenu) CallDLL #user32, "RemoveMenu", hMenu As ulong,_ hSubMenu As ulong, _MF_BYCOMMAND As ulong,_ RemoveMenu As boolean End Function
Other than making the fields in the substitute menu blank, I haven't worked out how it works, but it satisfied my need?
So, where do I start to have the ability 'in a years time to simplify and rewrite everything I have just coded in just 1000 lines'? I'm clearly still a caveman!
It's 5 pm right now, and my turn to cook dinner tonight, so thank you all again, take care and stay safe from Covid.
Kind regards, David
|
|
curly
Full Member
Posts: 161
|
Post by curly on Nov 25, 2021 12:43:46 GMT -5
I've found LB Command Reference - something to read and learn.
|
|
|
Post by Rod on Nov 25, 2021 14:10:18 GMT -5
I have amended the example code. I have amended it to deal with only the automatically added edit menu item that opening a texteditor causes. So The menu item to delete will be 0 not 1 as I do not add any menu items at the start. Alyce was showing how to remove an item from within a menu list. You simply want to remove the one and only menu item.
This results in the complete removal of the edit menu
NoMainWin
Texteditor #main.t,10,10,200,200 Open "A Window" For Window As #main #main "trapclose [quit]"
hMain=hWnd(#main) hMainMenu=GetMenu(hMain) hMainEdit=GetSubMenu(hMainMenu,0) result=RemoveMenu(hMainMenu,hMainEdit) Call DrawMenuBar hWnd(#main) Wait
[quit] Close #main:End
'functions: Sub DrawMenuBar hWnd CallDLL #user32, "DrawMenuBar",_ hWnd As ulong, r As boolean End Sub
Function GetSubMenu(hMenuBar,nPos) CallDLL #user32, "GetSubMenu",_ hMenuBar As ulong, nPos As long,_ GetSubMenu As ulong End Function
Function GetMenu(hWnd) CallDLL #user32, "GetMenu",hWnd As ulong,_ GetMenu As ulong End Function
Function RemoveMenu(hMenu,hSubMenu) CallDLL #user32, "RemoveMenu", hMenu As ulong,_ hSubMenu As ulong, _MF_BYCOMMAND As ulong,_ RemoveMenu As boolean End Function
|
|
|
Post by Brandon Parker on Nov 25, 2021 19:17:19 GMT -5
I would point out that what Rod posted is almost exactly what I posted the other day...
{:0)
Brandon Parker
|
|
curly
Full Member
Posts: 161
|
Post by curly on Nov 26, 2021 8:51:46 GMT -5
Rod and Brandon, Thanks for your patience while I am trying to learn. I am studying the code Rod just provided and trying to unravel it with the help of LB help, and I’ve added notes below of my thinking processes?
Your comments and corrections will be very much appreciated, Kind regards, David ps I'm not good doing things parrot fashion - I need to understand what I'm doing.
But first, using my ‘spaghetti code’, when I branch to a subroutine, where I branched from is stored in a stack (LIFO), and when the code of the subroutine has been run, the return command recovers the address from the stack, and the program continues to run from there. Too many gosubs without return causes a stack overflow where addresses keep being added and not deleted, and the program crashes.
Using the debugger and stepping through one line at a time, it appears that using LB Functions and CALLing SUBs, the function or subroutine is embedded into the compiled program at every location it is called from avoiding the need for stacks and branching?
Now Rod’s code. Windows has a reference or handle for everything, just as LB does, and if I want to use an existing windows routine to do something, (maybe because it cannot be done in LB or to avoid reinventing the wheel?.), then hwnd is the command that looks up the windows reference or handle so we can do something to it?– in this case, hMain would be a numeric variable that is the windows handle for my window #main
NoMainWin
Texteditor #main.t,10,10,200,200 Open "A Window" For Window As #main #main "trapclose [quit]"
hMain=hWnd(#main) 'hMain is the Windows handle for #main
hMainMenu=GetMenu(hMain) 'Function GetMenu(hWnd)runs using the Windows handle for #main to 'get the Windows handle for the menu bar as a 'positive long interger (ulong). hMainEdit=GetSubMenu(hMainMenu,0) 'Function GetSubMenu(hMenuBar,nPos)runs using 'the Windows handle for the menu bar and 'assigning value 0 to nPos to get the 'Windows handle for the menu as another positive 'long interger, Could nPos be the x position of 'the menu?????? result=RemoveMenu(hMainMenu,hMainEdit) 'Function RemoveMenue(hMenu,hSubMenu) runs here 'using the Windows handles for the menu bar 'and menu. Menu Bar and menu disappear? but I 'can’t work out why or the term result??????? Call DrawMenuBar hWnd(#main) 'Sub DrawMenuBar creates menu bar in #main – but 'struggling with r As boolean ??????? Wait
[quit] Close #main:End
'functions: Sub DrawMenuBar hWnd CallDLL #user32, "DrawMenuBar",_ hWnd As ulong, r As boolean End Sub
Function GetSubMenu(hMenuBar,nPos) CallDLL #user32, "GetSubMenu",_ hMenuBar As ulong, nPos As long,_ GetSubMenu As ulong End Function
Function GetMenu(hWnd) CallDLL #user32, "GetMenu",hWnd As ulong,_ GetMenu As ulong End Function
Function RemoveMenu(hMenu,hSubMenu) CallDLL #user32, "RemoveMenu", hMenu As ulong,_ hSubMenu As ulong, _MF_BYCOMMAND As ulong,_ RemoveMenu As boolean End Function
|
|
|
Post by Brandon Parker on Nov 26, 2021 9:19:37 GMT -5
David, I sent you a PM if you want to check it out.
You have the general gist of how the code above works.
A couple of things though: 1. Where ulong values are used, technically the value is an unsigned long 2. The return values of "RemoveMenu" and "DrawMenuBar" are better set as long values in LB instead of boolean values.
The menu is being removed with the "RemoveMenu" function, and when "DrawMenuBar" is called the menu bar is being redrawn, but there are no menus to be displayed. The menu bar itself is not being completely removed (in the code above or in my example). It does not hurt to not completely destroy the window's menu (menu bar) just in case you want to add one later. If you did want to completely remove the menu bar (which...again...is not being shown at the end of the code above ... and mine ... since no menus exist for it) you would simply add the function below and a call to it after the call to the RemoveMenu() function.
Function DestroyMenu(hMenu) CallDLL #user32, "DestroyMenu", hMenu As ulong, _ DestroyMenu As long End Function
{:0)
Brandon Parker
|
|
|
Post by Walt Decker on Nov 26, 2021 10:03:21 GMT -5
the function or subroutine is embedded into the compiled program at every location it is called from avoiding the need for stacks and branching? No. There are two types of spaces in an application, data space and code space. Code stays fixed in memory, data moves around. There is still a need for the stack. When the app is tokenized a number is generated that points (code pointer) to the location of the SUB or FUNCTION. When the SUB or FUNCTION is called the ARGUMENTS, i. e. the variables that are passed to the SUB or FUNCTION (e. g. CALL My.Sub A B C D) are placed on the stack plus the code address of the position at which the call was made and execution branches to the location in code space defined by the code pointer. The arguments (A, B, C, D) are pulled from the stack and used within the procedure. When the procedure completes it always branches back to the next instruction following the call assuming no critical error occurred. hwnd is the command that looks up the windows reference or handle so we can do something to it? Correct NoMainWin Texteditor #main.t,10,10,200,200 Open "A Window" For Window As #main #main "trapclose [quit]" hMain=hWnd(#main) hMain is the Windows handle for #main hMainMenu=GetMenu(hMain) Function GetMenu(hWnd)runs using the Windows handle for #main to get the Windows handle for the menu bar as a positive long interger (ulong). GetMenu() is a windows API function that returns the handle of a menu if present on the form window. In Lb there are 2 kinds of menus, those on the menu bar, and dropdown menus. The items on the menu bar have a numeric handle and a numeric position on the menu bar but no identification number. The items in a dropdown list have a numeric identification number and position but do not have a numeric handle. Putting the two together the application can determine which item was selected or which item to remove. hMainEdit=GetSubMenu(hMainMenu,0) Function GetSubMenu(hMenuBar,nPos)runs using the Windows handle for the menu bar and assigning value 0 to nPos to get the Windows handle for the menu as another positive long interger, Could nPos be the x position of the menu? ?? GetSubMenu() is an API function. In your case GetSubMenu is not necessary. However, the position is a numeric position, for example on the menu bar "Files" "Edit" "EXIT": "Files" is at position zero, "Edit" is at position one, "EXIT" is at position two. Each has a unique numeric handle but no identification number. In the dropdown list under "Files": "Load" "Save" "Delete" "Load", "Save", and "Delete" have a position under "Files" and an identification number that is defined by the program but no handle. "Load" is at position zero, "Save" is at position one, "Delete" is at position two. If you wanted to delete "Save" from the dropdown list you could do it by either position using the handle for "Files" or you could do it by using the handle of the menu and supplying the identification number. Right, clear as mud. CallDLL #user32, "RemoveMenu", _ '<--- function to remove a menu item hMenu As ulong, _ '<--- handle of menu hSubMenu As ulong, _ '<--- identificatio number of menu item _MF_BYCOMMAND As ulong, _ '<--- tells the function that it is a _ 'number and not a position RetVal As Boolean '<---RETURN: non-zero on success Boolean simply means that the function returns zero or non-zero(1 or -1). In your case you could simply do this: WinHndl = HWND(#main) '<--- get the form window handle
CALLDLL #user32, "GetMenu", _ WinHndl AS ULONG, _ '<--- handle of form window MnuHndl AS ULONG '<--- RETURN: numeric menu handle
CallDLL #user32, "RemoveMenu", _ '<--- function to remove a menu item MnuHndl As ulong, _ '<--- handle of menu 0 As ulong, _ '<--- position on menu bar _MF_BYPOSITION As ulong, _ '<--- tells the function that it is a _ 'position and not an identification number RetVal As Boolean '<--- 'RETURN: non-zero on success
CallDLL #user32, "DrawMenuBar, _ WinHndl AS ULONG, _ '<--- handle of form window RetVal AS VOID '<--- RETURN: we don't care
|
|
curly
Full Member
Posts: 161
|
Post by curly on Nov 26, 2021 12:35:52 GMT -5
Gents, I need to rinse my brain out with a drop of single malt! I'm in data overload!
I an going to study the ABC to API over the weekend, and respond Monday
Kind regards, thank you, stay safe
|
|
curly
Full Member
Posts: 161
|
Post by curly on Dec 1, 2021 5:15:04 GMT -5
Still studying!
|
|
|
Post by Walt Decker on Dec 1, 2021 13:28:56 GMT -5
David:
If you are trying to digest the Win API, that is probably not what you should be doing. The Win API is too vast to get your head around. I am constantly looking in my data base for API functions and examples of how to use those functions. If I can not find it in my data base I turn to the MS online data base and other sources online to get examples.
I think what you should be doing is learning how to write encapsulated code that you can write once and use again. For example, here is a little function that I use quite often:
WinHndl = FN.GetHandle("#DMO")
FUNCTION FN.GetHandle(WinName$)
Handle = 0
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ' If the first character in WinName$ does not equal the ' pound character then make the first character a pound ' sign '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IF LEFT(WinName$, 1) <> "#" THEN WinName$ = "#" + WinName$
'<--------------- HWND retrives handle of a form window or control ----> Handle = HWND(#WinName$)
FN.GetHandle = Handle '<--- return the handle END FUNCTION
A great many things can be done using native Liberty Basic statements and functions, but there is quite a bit that is either very difficult or not doable. That is when the Win API or 3rd party dlls come into play. That is when you should ask on this forum, "How can I do this either with native LB code or API? If with API please explain what you are doing?"
|
|