View Full Version : Thinbasic to write a two-level context menu handler à la 7Zip?
Winfried
27-12-2013, 22:41
Hello
I'd like to write a two-level context menu handler like 7Zip does (http://sourceforge.net/p/sevenzip/bugs/_discuss/thread/751e5e89/e2ae/attachment/7-Zip%20Make%20SelfExtractor%20Context%20Menu%20Option.png).
It appears that neither Freebasic nor Purebasic are good candidates so I was wondering if Thinbasic would be a good tool to write an extension, or if I really must dive into C++.
Thank you.
mike lobanovsky
29-12-2013, 07:35
Hello Winfried,
Welcome to the ranks and have a Happy New Year coming!
Your question is too ambiguous to be answered off-hand.
1. If what you want is create a right mouse click context menu for your own application, then any language that supports WinAPI calls can help you out with this even if its RAD has no user menu editor of its own. In this case your message simply isn't true. Such languages are FreeBasic, PowerBASIC, thinBasic, FBSL and perhaps a few dozens other BASIC dialects out there on the net including of course the notorious VB6. You are supposed to use appropriate WinAPI's for that like CreateMenu(), InsertMenu(), AppendMenu() etc. (google MSDN for more info on each of them). It's just a matter of using correct flags to generate the required types of menu items. This way, you can get a thousand-level context menu leaving 7-Zip sucking far, far behind. You can then spawn that multilevel menu in response to your right mouse click with a call to the TrackPopupMenu() WinAPI.
2. If what you want is just modify the existing 7-Zip drop-down menu as your picture in fact suggests, then it bears no relation to any programming language whatsoever, be it BASIC, or Java, or C++, or even Brainf*ck. Here's a complete heads-up (http://www.jfitz.com/tips/rclick_custom.html) on how system-level context menu items are created, modified, and deleted.
I could've invented a few more suppositions to discuss but my bet is I've already both formulated and answered what you in fact implied.
http://www.fbsl.net/phpbb2/images/smilies/icon_ml_noel.gif
Petr Schreiber
29-12-2013, 12:51
Hi Winfred,
if you want a context menu for dialog for example, here is demo code for you (tuned code by Eros from other thread):
Uses "UI"
Uses "Console"
' -- Menu IDs
Begin ControlID
%menu_Item1
%menu_Item2
%menu_SubItem1
%menu_SubItem2
End ControlID
Declare Function TrackPopupMenu Lib "USER32.DLL" Alias "TrackPopupMenu" (ByVal hMenu As DWord, ByVal uFlags As DWord, ByVal x As Long, ByVal y As Long, ByVal nReserved As Long, ByVal hWnd As DWord, lprc As RECT) As Long
' ----------------------------------------------
' Create main dialog
' ----------------------------------------------
Function TBMain()
Dim hDlg As DWord
Dialog New Pixels, 0, "Context menu demo",-1,-1, 320, 240, %WS_POPUP | %WS_VISIBLE | %WS_CLIPCHILDREN | %WS_CAPTION | %WS_SYSMENU | %WS_MINIMIZEBOX To hDlg
Dialog Show Modal hDlg Call cbDialog
End Function
' ----------------------------------------------
' Handling dialog events
' ----------------------------------------------
CallBack Function cbDialog() As Long
Local cr As CHARRANGE
Local pt As POINTAPI
Local lResult As DWord
Static hMenu As Long
Static hPopup1 As Long
Static hPopup2 As Long
Select Case Callback_Message
Case %WM_INITDIALOG
' -- First create a top-level menu:
MENU New Bar To hMenu
' -- Add a top-level menu item with a popup menu:
MENU New Popup To hPopup1
MENU Add Popup, hMenu, "Right click menu", hPopup1, %MF_ENABLED
MENU Add String, hPopup1, "Item 1", %menu_Item1, %MF_ENABLED
MENU Add String, hPopup1, "Item 2", %menu_Item2, %MF_ENABLED
MENU Add String, hPopup1, "-", 0, 0
' -- Now we can add another item to the menu that will bring up a sub-menu. First we obtain a new popup menu handle to distinuish it from the first popup menu:
MENU New Popup To hPopup2
' -- Now add a new menu item to the first menu. This item will bring up the sub-menu when selected:
MENU Add Popup, hPopup1, "More items", hPopup2, %MF_ENABLED
' -- Now we will define the sub menu:
MENU Add String, hPopup2, "SubItem 1", %menu_SubItem1, %MF_ENABLED
MENU Add String, hPopup2, "SubItem 2", %menu_SubItem2, %MF_ENABLED
Case %WM_RBUTTONDOWN
' -- Get position passed by event
pt.x = LOWRD(Callback_LParam)
pt.y = HIWRD(Callback_LParam)
' -- Convert local window position to screen position
Win_ClientToScreen(Callback_Handle, pt)
' -- Show and Handle menu.
' -- Important: use %TPM_RETURNCMD otherwise the choosed command will not be returned
lResult = TrackPopupMenu(hPopup1, %TPM_LEFTALIGN Or %TPM_RIGHTBUTTON Or %TPM_RETURNCMD, pt.x, pt.y, 0, Callback_Handle, ByVal %NULL)
End Select
End Function
If you need a context menu in shell, I think you need to dive into COM and implement class satisfying IContextMenu interface.
Writing COM DLLs is a lot easier in PowerBASIC than in C++, ThinBASIC cannot serve here, as it cannot create DLLs.
Petr
John Spikowski
29-12-2013, 21:13
If you need a context menu in shell, I think you need to dive into COM and implement class satisfying IContextMenu interface.
Writing COM DLLs is a lot easier in PowerBASIC than in C++, ThinBASIC cannot serve here, as it cannot create DLLs.
A better solution is using OxygenBasic to create your COM interfaces dynamically (JIT) in memory like I do with ScriptBasic and Charles's DLLC extension module.
'COM SPEECH
VoiceObjGuid = dllguid("96749377-3391-11D2-9EE3-00C04F797396")
ISpVoiceGuid = dllguid("6C44DF74-72B9-4992-A1EC-EF996E0422D4")
Context = 7
pUnkOuter = 0
Voice = 0
Release = dllmeth( 2,"Release i=()")
Speak = dllmeth(20,"Speak i=(t*pwcs,i flags,i pulstreamno)")
WaitUntilDone= dllmeth(32,"WaitUntilDone i=(i)")
print dllreco(speak)
Text = dllwstr("Hello ScriptBasic")
hr=0
dllcall(CoInitialize,0)
hr=dllcall(CoCreateInstance, VoiceObjGuid, pUnkouter, Context, ISpVoiceGuid, Voice)
if (hr=0) then
print "connected to voice\n\n"
print dllastr(Text) & "\n\n"
dllcobj(Voice,Speak,Text,0,0)
dllcobj(Voice,WaitUntilDone,0xFFFFFFFF)
dllcobj(Voice,Release)
else
print "SAPI Error " & format("%x",hr) & "\n\n"
end if
dllcall(CoUninitialize)
ErosOlmi
29-12-2013, 22:32
What is DLLC?
John Spikowski
29-12-2013, 23:17
It is the FFI+ extension module for ScriptBasic that Charles wrote. It also gives SB multi-threading and a common callback handler so SB scripts can be the callback routines for IUP applications. It even allows running existing DLL functions in their own thread. A true work of art. Too bad I hate Windows and hope to make DLLC portable with C BASIC some day.
If I'm not mistaken, much of the work done for DLLC was migrated into the current round of thinBasic O2 enhancements. You should be able to do the COM interface with what you currently have. Charles will have to expand on this from here.
mike lobanovsky
30-12-2013, 00:04
John,
It seems like what you're talking about is calling a 3rd-party system-wide inproc server (COM DLL) from within a language which is a rather common feature for a modern interpreter under Windows. What Petr implies is rather creating an application that would implement an IContextMenu interface and behave like (in fact, be) an inproc server (COM DLL) itself. That would allow the application to create entries in the system-wide context menu in order to expose its user interface. This is what 7-zip.dll is responsible for in the 7-Zip archiver installation.
Interpreters cannot normally create COM DLL's unless they have an ability to translate, compile, and link their scripts to native code binaries, sometimes via assembly, sometimes via C, and still sometimes directly (without the aid of 3rd-party static compilers and/or linkers) that would satisfy the operating system's binary interface requirements to an inproc server (a.k.a. COM DLL, COM component, ActiveX object).
PowerBASIC 10 can do that easily while thinBasic cannot, to the best of my knowledge. I don't know if Oxygen Basic currently supports BASIC code compilation to a COM DLL or not.
John Spikowski
30-12-2013, 05:30
The ScriptBasic / DLLC example I posted the code for is doing low level (direct) calls to the Windows SAPI (Speech API) COM services. Just as PowerBASIC could do using Jose Roca's type lib browser and PB code generator. I'm sure Charles could explain it better as he wrote and tested the interface.
ErosOlmi
30-12-2013, 15:48
It is the FFI+ extension module for ScriptBasic that Charles wrote. It also gives SB multi-threading and a common callback handler so SB scripts can be the callback routines for IUP applications. It even allows running existing DLL functions in their own thread. A true work of art. Too bad I hate Windows and hope to make DLLC portable with C BASIC some day.
If I'm not mistaken, much of the work done for DLLC was migrated into the current round of thinBasic O2 enhancements. You should be able to do the COM interface with what you currently have. Charles will have to expand on this from here.
Thanks John,
I looked inside DLLC source code from Charles (found into \OxygenBasic\ProjectsB\ScriptBasic\Dllc.o2bas of Oxygen source code) but honestly it is too complex for me: I understand the main design but I loose the details.
I was interested on how to scan COM objects to dynamically get at run-time interfaces/properties/methods/parameters/enums/... but I see you have to define in your scripts manually so this is not my direction.
Ciao and thanks anyway.
Eros
John Spikowski
30-12-2013, 20:04
DLLC only provides to the tools to access COM interfaces. There is no SB typelib browser generating SB COM definition scripts. When I get some time, I would like to use the SB MODULE/END MODULE feature to encapsulate a COM interface making it a IMPORTable object one could use with their SB scripts. If I could only sell Jose Roca on the benefits of using an interpreter and open source, he would be the perfect candidate to create these COM MODULEs. Which may work with MONO on Linux/OS X.
FYI IUP provides COM container support (see embedded web browser example for Windows) that could be used with SB & DLLC.
Winfried
04-01-2014, 23:44
If you need a context menu in shell, I think you need to dive into COM and implement class satisfying IContextMenu interface. Writing COM DLLs is a lot easier in PowerBASIC than in C++, ThinBASIC cannot serve here, as it cannot create DLLs.
Thanks all for the infos.
Indeed, I'd like to write a multi-level Windows Shell context menu handler so that it's added to Windows Explorer.
So apparently, ThinBasic cannot be used to build a COM DLL, and I should look at those alternatives:
OxygenBasic
ScriptBasic + DLLC
PowerBasic 10