• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

PowerBasic or Visual Basic?

Started by James McNab, September 06, 2010, 04:55:22 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

I am always using the Flat API and the procedural model, even with Dot.NET, because this make my code highly portable from one platform to another, and from one language to another.  8)

For me using PB with the SDK syntax, is like writing C with a "basic" syntax. Hower understanding C is a mandatory when you want to learn and use the latest technology (see the Direct2D examples posted by José and myself).

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Frederick J. Harris

Hadn't ever really thought of this before, and in terms of some of Chris's comments about preferring 'regular exported procedural' type Dlls rather than dlls containing code in the form of COM objects, I can't see any reason why it has to be 'either/or'.  Couldn't you put both regular exported procedural code plus COM components in the same Dll?  After all, even the COM runtime has to use a plain ordinary exported procedural function - DllGetClassObject(), to get its first pointer to an objects's VTable.  So what I'm saying is that if you don't like the registry you could still stick your favorite procedural functions in a dll, intermixed with COM objects which could be loaded with DllGetClassObject().  If you don't want to use the Service Control Manager (SCM) to load the COM objects you could even do it yourself.  Like I said, I hadn't ever done this, but see no reason why it wouldn't be fine.  Jose?

José Roca

#32
 
This is all you need to do to load and activate an in-process COM server:


LOCAL hr AS LONG                           ' // HRESULT
LOCAL hLib AS DWORD                        ' // Library handle
LOCAL szLibName AS ASCIIZ * %MAX_PATH      ' // Path of the COM server
LOCAL pProc AS DWORD                       ' // Procedure address
LOCAL pIClassFactory AS IClassFactory      ' // IClassFactory interface
LOCAL pUnk AS IUnknown                     ' // The requested interface pointer
LOCAL rclsid AS GUID                       ' // CLSID that will associate the correct data and code
LOCAL riid AS GUID                         ' // IID of the interface to be used to communicate with the newly created objec

szLibName = <Path of the server>
rclsid = GUID$("<guid of the class>")
riid = GUID$("<identifier of the interface>")

' // See if the library is already loaded in the address space
hLib = GetModuleHandle(szLibName)
' // If it is not loaded, load it
IF hLib = %NULL THEN hLib = LoadLibrary(szLibName)
' // Retrieve the address of the exported function DllGetClassObject
pProc = GetProcAddress(hLib, "DllGetClassObject")
' // Request a reference to the IClassFactory interface
CALL DWORD pProc USING DllGetClassObject(rclsid, $IID_IClassFactory, pIClassFactory) TO hr
' // Create an instance of the server or control
hr = pIClassFactory.CreateInstance(%NULL, riid, BYVAL VARPTR(pUnk))


No registry entries, no type libraries, no DLL/OCX hell, no nothing.

It is like the the old good LoadLibrary/GetProcAddress to call procedural functions, with the difference that, instead of getting the address of a single function, you get the address of a pointer to a virtual table to the addresses of the several functions (they are called methods in COM lingo, but are the same that procedural functions) that integrate an interface.

Looks as if most ex-VBer's are spoiled for life to understand low-level COM.

A COM server, DLL or OCX, can of course contain procedural functions, exported or not, for the simple reason that it is not a different kind of DLL, but a standard DLL.

Edwin Knoppert

Maybe it is even useful on .NET assemblies which are com-exposed, not sure, should be i guess.

Frederick J. Harris

Quote
Looks as if most ex-VBer's are spoiled for life to understand low-level COM.

No, I've understood that quite well for a long time now, and have lots of examples of doing just that down in my COM tutorials.  Its just that the idea of exporting additional functions besides the four required by COM (DllCanUnloadNow, DllGetClassObject, DllRegisterServer, DllUnregisterServer) struck me as a novel and interesting proposition that I hadn't really thought of before, but its possibility simply follows from the fact that you have tried to make plain many times here and elsewhere, and that is that the Dlls that house COM objects aren't special in any way; they are just ordinary Dlls which must export several specific functions if they are to be accessed by the COM implementation within Windows. 

And I don't think all the VB'ers were ignorant of code writing skills.  Maybe a lot of them but not all.  Especially in the field of database projects, VB was simply easier to use to put a sophisticated database back end plus front end together than any of the C/C++ oriented tools, and I think a lot of experienced coders from other languages moved to VB.  That was back in the nineties.  Where they all scattered to now I don't know; probably most to .NET and PB picked up a few here and there.

The only issue that strikes me as one that would take special care regarding mixing one's own procedural library functions in a dll mixed with COM objects is that one wouldn't want COM reference counting mechanisms to unload the Dll ignorant of the fact that it was still being used in terms of simple procedural functions contained within it.

José Roca

 
It won't happen because LoadLibrary also keeps a reference count.

Quote
The system maintains a per-process reference count on all loaded modules. Calling LoadLibrary increments the reference count. Calling the FreeLibrary or FreeLibraryAndExitThread  function decrements the reference count. The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count).


José Roca

 
There are many servers that mix procedural functions and interfaces, such urlmon, htmlhelp, ATL, Direct 2D and even the .NET runtime.

José Roca

Quote
And I don't think all the VB'ers were ignorant of code writing skills.  Maybe a lot of them but not all.

I said that "Looks as if most ex-VBer's are spoiled for life to understand low-level COM." And this is not a judgement about their code writing skills. If I had been a VB user, probably I would not have learned anything about low-level COM. I learned it out of necessity.

But many have the misconception that COM is bloated, slow and evil. And it is not. Low-level COM was designed by C programmers and is pretty straightforward and not much different as using procedural functions. I started using it with PB writing procedural wrapper functions that used CALL DWORD and function prototypes.

Automation was designed by the Visual Basic team, and to allow to use it filling values in the properties grid individually, they come with the get/set properties (there are only methods in low-level COM). Therefore, where low-level COM servers use methods with several parameters, just like procedural functions, Automation servers designed to be used in visual designer come with properties for each value. And many OCXs incorporate their own property dialogs, some of them very sophisticated, that add a lot of bloat to the server and are only needed by visual designers.

And then, to provide intellisense, they needed to have the interface definitions, and they invented the type libraries, that add more bloat to the server, unneeded to work with it because they only are needed by the visual designer.

They also wrapped the common controls with OCXs, to allow to use them filling values in a property grid and to provide intellisense. And because they are ActiveX controls instead of custom controls, they need an OLE container. More bloat.

And then invented new data types, variants and safe arrays, and forbid the use of pointers and null-terminated strings because VB doesn't support them. With low-level COM you can use all the same data types that with procedural functions and in the same way.

And then all that registration mess that originated the OCX hell.

etc...


Frederick J. Harris

#38
Quote
It won't happen because LoadLibrary also keeps a reference count.

I was thinking that too, but wasn't sure.

Sounds like you dislike anything having to do with IDispatch, and anything having to do with supporting property sheets and all the rest of the interfaces that go along with ActiveX controls able to be hosted by scripting languages Jose.  I can't say I blame you because I've studied all your code and everything you had to go through when you first figured out how to get those things to work with PowerBASIC 7 back around 2005.  Talk about jumping through hoops (an American English colloquialism meaning having to endure tremendous trials and difficulties to accomplish something).  Talking about colloquialisms, this thread's starter used one many here on the continent might not be familiar with and that is the 'not in Kansas' bit.  That's actually a somewhat rare and unusual American English expression whose meaning is something to the effect that we're not living in rustic farm like simplicity anymore in the field of programming (Kansas is a mostly rural and agricultural area of the American mid-west).  Just though I'd mention this sort of thing because I guess I'm the only one of the moderators here on Jose's forum that speaks native American English, and I oftentimes lapse into colloquialisms that in afterthought I realize may not be understood.  And I have nothing but the highest respect for all the PowerBASIC members whose primary language isn't English but have managed to learn it.  I myself studied German for many years but eventually discontinued my study of it.  I simply had no one with whom to converse (Leider hatte Ich niemand mit dem zu sprechen!), as here in America almost nobody speaks more than one language (and the folks from England maintain we can't speak English either!). :)      

Frederick J. Harris

#39
Also, regarding your comments Jose about all the bloat associated with *.ocx (ActiveX controls used in VB) controls, I've been experimenting a lot lately with creating visual COM controls, and what I've discovered so far is that it takes very little to create one.  If you recall that custom control demo I posted quite a while back (there were buttons on the host which caused the custom control to turn blue, green, or red, and when you clicked on the control it SendMessage()'ed a WM_NOTIFY back to the host), I created a COM object out of that, and to get it to be recognized in both VB or PB9 in terms of a sink object all I implemented was a simple out going interface and IConnectionPointContainer and IConnectionPoint.  And I didn't even implement all the methods in those interfaces; only the ones I needed, i.e., Advise, Unadvise, FindConnectionPoint, etc.  I didn't do any of the enumerators.  I didn't mark it as a 'control' in the typelib, and probably because of that it doesn't show up on the 'Components' tab within Visual Basic where users choose and insert such things, but as I said, it does show up in the COM 'References' tab in Visual Basic, and Visual Basic seems quite happy to dynamically generate a sink for it and accept outgoing method calls on it; likewise PowerBASIC 9.  

It seems like I've found a methodology to create these things low level which would be useful to me, i.e., visual COM controls, but I'm not quite sure what to call them besides visual COM controls.  I believe ActiveX controls mostly implement piles of additional interfaces that ADD ALL THE BLOAT OF WHICH YOU ARE SPEAKING, i.e.,

IPropertyNotifySink
ISpecifyPropertyPages
IPropertyPage(2)
IOleInPlacrActiveObject
IViewObject(2)
IViewObjectEx
IOleInPlaceObject
IOleInPlaceObjectWindowless
IOleControl
IOleObject
IOleWindow
IDataObject
IQuickActivate
IPersist
IPersistStorage
IPersistStreamInit
IPersistPropertyBag
IProvideClassInfo(2)

and at this point I'm not really sure what to do with all those interfaces, if anything.  From what I've gathered/learned so far, most or all of those interfaces pertain not so much to the fundamental working of the control, but to providing a design environment with which such design containers  as Word and Visual Basic can provide a visual design experience to the user involving the control.  Is my understanding of that anywhere close to the truth?
     

Frederick J. Harris


José Roca

 
Quote
Sounds like you dislike anything having to do with IDispatch, and anything having to do with supporting property sheets and all the rest of the interfaces that go along with ActiveX controls able to be hosted by scripting languages Jose.

So right. I'm not a "drag and drop" programmer.

Quote
I can't say I blame you because I've studied all your code and everything you had to go through when you first figured out how to get those things to work with PowerBASIC 7 back around 2005.  Talk about jumping through hoops (an American English colloquialism meaning having to endure tremendous trials and difficulties to accomplish something).

I believe that first you have to learn how to do it the hard way. You have to understand how things work to become a developer and not just a coder or tool user.

Quote
And I didn't even implement all the methods in those interfaces; only the ones I needed, i.e., Advise, Unadvise, FindConnectionPoint, etc.

And using low-level COM you can use any class that inherits from IUnknown as the event sink and call the methods directly using any data type, without having to go through the IDispatch way and all that Variant conversion crap.

Quote
I believe ActiveX controls mostly implement piles of additional interfaces that ADD ALL THE BLOAT OF WHICH YOU ARE SPEAKING, i.e.,

Many of them are to communicate with the OLE container and the others with the visual designer.

The newest ribbon framework has not been implemented as an ActiveX control. It simply renders in the window you provide, without the need for an OLE container. But, of course, M$ had to spoil it with the use of manifests and even a new lenguage (the ribbon markup) and a compiler (the UI Command Compiler) for it to describe the controls and their properties.

Quote
And what happened to James McNab?  ???

Posts of the kind This vs That are usually meant to promote flame wars.

Frederick J. Harris

Quote
Many of them are to communicate with the OLE container and the others with the visual designer.

I need to study up on that.  Its a big area of misunderstanding, or lack of understanding on my part.  And I am aware it is something of an important topic that I need to grasp.  I'm even afraid to ask any questions about it of you because I feel they would be so dumb due to my lack of understanding.  For example, if I want to put an edit control or a listbox on a form/dialog/window I certainly don't need to create another window to be its parent and 'contain' it.  When I created that custom control demo of which I spoke above (and the idea for which I got off Chris Boss's custom control tutorial), I just created the custom control on the main program's window through a CreateWindow() call (the class was naturally registered in the Dll through its loading) and I didn't need any 'container'  other than of course the main program's main window.  So why with all this ActiveX stuff is a 'control container' even needed???  Way back when you first figured out how to use the popular Visual Basic ActiveX Controls MSFlexGrid.ocx and the Calendar control I noted they needed to be created within 'containers'.  You provided such simple things as "static" controls to be their containers, and if I recall the hWnd was passed to some AtlCreateControl() type functions.  Then later you created your OleCon.bas code to act as containers for these controls.  What in the world is going on here if you don't mind telling me or pointing me in the direction of some link that might explain it in a fashion that someone that isn't a genius can understand?

In my various studies I've come across the terms windowed verses windowless controls, and I've read up on them, but unfortunately, I still don't understand something perhaps fundamental that is going on here.  I guess I don't understand how a control wouldn't create a window for itself.  Oftentimes I think things are more complicated than they really are, and maybe this is one of those.  Is this situation so simple that its just a matter of who is going to provide the top level container for the control, that is, the client will create a window and pass its hWnd into the control for it to use, or in the other scenerio, the client will make some kind of COM method call on the object such as Object.CreateControl(25,50,75,100) and pass in client coordinates as to where drawing is to occur on the main program window?  I guess in this latter case the control would still need a hWnd from the client to do anything at all on the client window???  I have been musing over this for a couple years actually.

     Well, we're all pretty level headed here I think and don't really engage in flame wars, even though we are passionate about what we do.   

Edwin Knoppert

Frederick, can you post a small example to create a visual activex control? :)

José Roca

 
Quote
So why with all this ActiveX stuff is a 'control container' even needed???

Custom controls are designed to be childs of a window. ActiveX controls are designed to be embeddable objects that can also be placed in a web page or a Word document, for example. The container provides services to them and the communication between the container and the controls is done with COM, not via SendMessage.

Windowless controls don't create its own window and, therefore can't process Windows messages, having to delegate this task to the container's window, that after processing the message resends the information to the control. They were dessigned mainly to be used with Internet Explorer, because a web page can have many embedded controls and if each one has its own window there is a waste of resources. When drawing itself, a windowless control asks the container to provide a device context and returns the device context to the container after drawing into it. This improves the performance of the control.