General Development Issues|
Questions about source code strategy How would I do it if I wanted to use runtime binding? What is the purpose of the window property 'STOBJ'? Handling Windows Messages Getting Started with Projects... Debugging an Executable How do I stop a thread? MappedObjectStream only stores one object Sample Code: Loading and unloading ActiveX Controls dynamically
What follows is a description of the files that you must or may ship with a Smalltalk MT executable:
Note: strtdllx.DLL is named strtdll20.dll in Smalltalk MT 2.0 and strtdll25.dll in version 2.5/2.6. Strictly speaking, runtime Dlls are not version-dependant. We changed the functionality exposed by the runtime Dll. In addition, the latest Dlls have been compiled with VC 6, which resulted in an increase in code size.
The message #_asCinteger is sent implicitly to API arguments, and returns a 32 bit representation of an object. If the object cannot be passed to an API (for example nil), it raises an exception.
You can bypass this message with one of the messages #basicAddress,
#_asInteger, or more generally with an inline message that returns a known type
(such as #_longAtOffset:).
Note that the address manipulation methods (#atAddress:put: etc.) do not send the message, so you may have to send it yourself if the parameter is not an integer or LONG type. Example: MemoryManager atAddress: ppEnumConnectionPoints put: ienum _asCinteger.
It would be similar to what you do in C:
You can take a look at #callProc:with:with: and add more
parameters as you
Each window implements its own window procedure (although most windows inherit the default window procedure in Window), and exports it to the operating system.
A Smalltalk-created window other than a dialog box reserves private data in its window creation structure, and stores the address of the Smalltalk object in that slot (remember: in ST/MT, objects are never moved).
A DialogBox functions exactly like a Dialog Box in C/C++ ; each instance has its own dialog procedure that references the Smalltalk object.
The purpose of this property is to be able to retrieve the Smalltalk object associated with a window, given the window handle. If the window is not maintained by Smalltalk (i.e., the window procedure is implemented elsewhere), the property will not be set.
The return statement in a block returns from the method that defines the block. If you create a thread that executes this block, the new thread would attempt to return from a method context in a parallel thread, therefore switching the stack and crashing. And your original thread would crash as well because the other thread corrupted its stack. Therefore, the code that actually returns verifies that the return is valid, and raises a software exception if it cannot return.
A forked block exits naturally. If you created the thread with one of the #fork messages, there is no need to worry about exiting the thread. For example:
exits when it is done.
In Win32, the only general way to kill a thread is to use TerminateThread. This works on Smalltalk MT created threads as well, but leaves some Win32 resources open (refer to the Win32 documentation).
So, terminating a thread in an orderly fashion requires some programming logic and synchronization. The Philosopher sample shows how to do this.
A Windows Application requires at least the following components:
In order to open an application such as Generic, you must first install the project file (generic.sp). The next step is to copy the resources into your path (i.e., copy generic.dll to your image directory). You can then open the application (look at the readme.txt file that comes with the sample to see how to do this).
Some projects require additional components before they can be used. The Project Browser will take care of it automatically (linking with DLLs and installing prerequisite projects).
You must first define a method ApplicationProcess>>winMain:with:with:with: that starts up your main window (or whatever you want to do in the process). Define this method in a file called winmain.sm and place the file in the project directory.
The Project Browser checks for a winmain.sm file in the current project directory before it enables the build EXE menu item.
The generated executable raises an exception at runtime:
If you enable all error assertions you'll see the message box of the type "an instance of XXX did not understand Symbol(yyy), the message was sent by an instance of ZZZ".
In the development, evaluate
and it returns #show:.
You can also run the executable in WinDbg or use DBMON on Windows NT to view debugging messages.
a) #basicAddress always returns an integer that is the object's address.
b) once you take an object's address, you must ensure that it is still referenced. The following is wrong:
c) to be sure an object is not discarded, you can:
To process a window message such as WM_MOUSEMOVE, just implement a method named WM_XXX:with: (for a WM_XXX message). Don't forget to return a value as specified by the documentation of the message.
If the window that receives the message is a Windows control, the method above will not directly work because the window procedure is implemented by the control. First, check whether the control send notification events to its parent. In this case, install an event handler for the notification (using #when:in:perform:). Otherwise, create a Smalltalk subclass of the control that implements the windows message in question, and send it the message #subclassWindow upon creation. The TwinEdit sample on the distribution set demonstrates this.
To exit the development environment programmatically, evaluate:
In Smalltalk MT, the standard serialization methods use memory-mapping technology. MappedObjectStream implements an easy-to use interface. An instance of MappedObjectStream maps a set of objects into the address space of the process. The top-level object is called the root object. There is only one root object, but it can be arbitrary, and in particular it can be a collection.
If you open an existing file in RW mode, you can modify any object that resides in the file. When the file is saved, external references are automatically appended to the end of the file. If you wish to add more objects, you can add them to the root collection or to any other object in the file.
See also Object Serialization Example.
The garbage collector (GC) scans all object references. If you close the mapped file while keeping a reference, an otherwise valid reference will suddenly point to nowhere. The GC algorithm assumes that an object reference is always valid. Otherwise, object traversal would be much slower.
See also Object Serialization Example.
It is possible to load and unload ActiveX controls at runtime. One benefit is that an application can delay loading an ActiveX control until it is actually needed, which reduces the application startup time.
The following code fragment loads an ActiveX control (the Microsoft Web Browser Control) dynamically. The application must first create an OleContainerWindow.
To unload the control:
Visitors Since 1/1/2000: