SilverPlus Development Reference

Table of Contents

Introduction

SilverPlus Development
About This Document
Document Conventions

SilverPlus Application Development

Overview
DLL Compatibility
Basic Terms
Requirements
     Using a C DLL
     Using an MFC DLL
     The SilverCExec function
DLL Startup
Calling Conventions
     The __stdcall Calling Convention
     The __cdecl Calling Convention
Building SilverC DLLs Using the MFC Wizard
     Files Used in the Project
     Generating the DLL Skeleton
Using the REX Interface with Windows DLLs
A Note on Resources
DLL Debugging Techniques
A Note on Command IDs
Window Subclassing
SilverScreen Architecture
     SilverScreen and MFC
     SilverScreen Input Processing
The WM_FEED_CHAR Message
The DLL Developer Problem Solver
     Displaying Menu Text on the Status Line
     Handling CmdUI for Developer IDs
     Changing the Mouser Cursor Shape
     Calling C++ from C

Sample Projects

SCDLL
MFDLL
ScriptWin
Preview
DLLStuff

 

Table of Exhibits

 

Introduction

SilverPlus Development

SilverPlus is the environment used for developing Windows applications that run under SilverScreen. Such applications are implemented as DLLs loaded under control of a SilverC program. SilverPlus applications use the SilverScreen API, which is the common set of functions used to develop application programs that use SilverScreen Solid Modeling technologies. This manual contains information about developing SilverPlus DLLs.

We also assume some familiarity with the C/C++ languages and SilverScreen operation, plus some understanding of 3D concepts. For more complete coverage of SilverScreen, see the SilverScreen Reference Manual.

About This Document

This document describes the SilverPlus development system, which is a method used to build applications that utilize the SilverScreen Solid Modeler.

Document Conventions

Important type styles and conventions used in this document:

  • Groups of text lines, indicating C program source or script command sequences are set off from normal text as follows:

    void main( void )
    {
    ss_command( "note Hello world" );
    }

  • C keywords, variable names, C source file names and other C language components embedded in the text are set off as follows:

        strcpy( msg, "a message" );
  • A sequence of three dots indicates that a part of a program or sequence has been omitted:

    ...

  • Italicized words denote placeholders for unspecified text; these may be enclosed in less-than/greater-than signs for clarity:

identifier
<bos name>

  • Script commands (or portions thereof) appearing in text are bold-faced:

    isolate object arm

 

 

SilverPlus Application Development

Overview

Under the DOS version of SilverScreen, the only way to link to native code for purposes of execution speed was to use the REX file interface. Under Windows, a similar approach available is available by using an executable library known as a DLL, short for (Dynamic Link Library). A DLL is a collection of resources such as code, data, graphical elements etc. For the purposes of extending SilverC, a DLL must have executable code in it.

Unlike DOS, a DLL is useful not only for accessing native code for speed, but also the ability to incorporate native Windows user interface elements such as menus, dialog boxes and toolbars into your application.

SilverScreen does not directly load DLLs for 3rd party use; the 3rd party developer must write a SilverC application to manage the loading and unloading of DLLs, and also to direct flow of execution into and out of the DLL. A SilverC program does this by using the REX interface: rex_load, rex_unload and rex_exec.

Execution of a SilverPlus DLL

The SilverC program is initiated via the EXECUTE command.
The SilverC program loads the DLL via the rex_load function and uses rex_exec to invoke the DLL code.
The DLL communicates with SilverScreen via SendMessage, subclassing, SilverScreen API, etc.

Exhibit 1.  Execution of a SilverPlus DLL

DLL Compatibility

There are many tools that may be used to build DLLs, however, we recommend using Microsoft’s Visual C++ package (MSVC++), as that is what we use to build SilverScreen. By using MSVC++ and the MFC DLL libraries, you can cut down on the amount of code that is linked into your DLL. We believe that other packages may also be used, some of which use licensed versions of MFC, but we have only ever tested with MSVC++.

If you are using DLLs to extend SilverScreen functionality, and you use either the MFC library or the C runtime library, it is essential that you use the identical DLLs that SilverScreen is using. If you do not, then it is very likely that SilverScreen and your app will crash. This includes the cases where you are running under a release version of SilverScreen or a debug version.

The SilverScreen Developer’s Kit is designed to be used with version 6.0 of the Microsoft Visual C++ compiler. SilverScreen makes use of the following MSVC DLLs:

DLL Release Version Debug Version
MFC DLL MFC42.DLL MFC42D.DLL
C Runtime DLL MSVCRT.DLL MSVCRTD.DLL

Basic Terms

A DLL in the Windows environment is a collection of resources including executable code, graphical elements like dialog templates and menus, and data, such as strings. The acronym DLL stands for Dynamic Link Library, and it indicates that that the library is loaded dynamically by an executing program. A SilverC application may use a DLL to perform calculations at native code speed or to access Windows functionality not provided by the SilverC runtime library.

Requirements

We here describe two ways to build DLLs for use by SilverScreen. One way is to build a C DLL, specifying your own DllMain DLL entry function. The other is to make a C++ DLL, with a CWinApp derived class that serves as the base of the application (the DllMain function is embedded implicitly in this construct). Both methods require that there be an exported function named either SilverCExec or _SilverCExec that SilverScreen will use to communicate with the DLL.

Using a C DLL

If you choose to use a C DLL, then you will need to provide a DllMain function.

The DllMain function is a requirement for Win32 DLLs. The DllMain function is called just after your DLL is loaded, and again just prior to its removal. DllMain is also called when the SilverScreen process creates or destroys a thread. DllMain is used to initialize the DLL; in particular, the C run-time library and some static C++ objects are initialized then, also, an important piece of data -- the instance (or module) handle for the DLL -- is passed to DllMain when the DLL is being loaded. The instance handle is necessary for loading other resources from the DLL module.

Note that under some uses of the MFC for DLLs, the DllMain function is hidden inside the MFC mechanisms. See the MFC example.

The prototype for DllMain should match the following:

extern "C" int __stdcall
DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved );

where hInstance is the DLL module handle, and where dwReason is the reason for the DllMain call.  dwReason may be one of the following

DLL_PROCESS_ATTACH
DLL_PROCESS_DETACH
DLL_THREAD_ATTACH
DLL_THREAD_DETACH

lpReserved reserved by Windows

Exhibit 2 contains a simple skeleton for a C DLL, including a SilverCExec function.

Using an MFC DLL

If you choose to use an MFC DLL to extend SilverScreen, then you may use the AppWizard in Microsoft Visual C++ to provide the skeleton. We recommend that you use specify a regular DLL using the MFC library implemented as a shared DLL. The procedure for starting such a DLL is found in Building SilverC DLLs Using the MFC Wizard.

The SilverCExec Function

Note: This section assumes that the compiler being used is Microsoft’s Visual C++.

The SilverCExec (or equivalently, _SilverCExec) function is required by the SilverC DLL loading and unloading code. It is used to pass the SSREX pointer sc down to the DLL (SSREX is a structure containing function pointers corresponding to members of the SilverC library), so that SilverC functions may be used by the DLL. It is also used by a SilverC program to call into the DLL, thus serving as the gateway between SilverC and the DLL.

The prototype for SilverCExec should match the following:

extern "C" __declspec(dllexport) int SilverCExec( int op, void *data );

That is:

  • C linkage
  • exported (by __declspec(dllexport) or other means)
  • __cdecl calling convention

Where:

op a user-defined operation code; with the exception of anything less than the value of REX_USER_BASE, which is reserved for SilverScreen library initialization

data is dependent on the operation code; in the case where op is equal to REX_FIRST_LOAD, this will be a pointer to an SSREX structure. The alignment for members of structures passed via data (including the SSREX) structure must be 4 bytes.

#include <windowsx.h>
#include "silver2.h"

SSREX *sc;
#if defined(__cplusplus)
#define export extern "C" __declspec(dllexport)
#else
#define export __declspec(dllexport)
#endif

export BOOL APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
   {
   // DLL Initializing
   }
else if (dwReason == DLL_PROCESS_DETACH)
   {
   // DLL Terminating
   }
return 1; // ok
}

export int SilverCExec( int op, void *data )
{
switch ( op )
   {
   case REX_FIRST_LOAD:
        sc = (SSREX *) data;
        break;
   case REX_LOADING:
        break;
   case REX_UNLOADING:
        break;
   case REX_REMOVED:
        break;
   }
}

Exhibit 2.  Sample Skeleton for a C DLL

DLL Startup

A SilverScreen DLL is loaded by calling the SilverC library function rex_load. Internally, rex_load operates by calling the Win32 function LoadLibrary. If the DLL is found, LoadLibrary attempts to load it, and in doing so, calls the DLL entry function (DllMain in our case). In addition, if it is a C++ DLL, then all global objects are initialized (i.e., the constructors of global objects are invoked, including that of the CWinApp derived main class). At his point in execution, the SilverCExec function has not been called, so you may not yet call SilverC functions (i.e., not in the DLL_PROCESS_ATTACH section of DllMain, or in the constructor for your CWinApp derived class). Provided all goes well, the library is successfully loaded, and then SilverScreen attempts to locate the SilverCExec (or _SilverCExec) function in the library (by using GetProcAddress). If neither SilverCExec nor _SilverCExec is found, then the load fails, and rex_load returns 0. Otherwise, the DLL was previously loaded, but not unloaded, then SilverScreen calls SilverCExec with an op value of REX_FIRST_LOAD. At this point, the SSREX pointer will be passed as well, and the DLL should store this pointer in a variable so that the DLL can call SilverC functions. Following this, SilverScreen calls SilverCExec with a value of REX_LOADING. rex_load then returns a handle which should then be used in subsequent calls to rex_call and rex_unload.

Calling Conventions

The __stdcall calling convention

The __stdcall calling convention is used to call Win32 API functions. The called function cleans up the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype. The following list shows the implementation of this calling convention.

Element Implementation
Argument-passing order Right to left
Argument-passing convention By value, unless a pointer or reference type is passed
Stack-maintenance responsibility Called function pops its own arguments from the stack
Name-decoration convention An underscore (_) is prefixed to the name. The name is followed by the at-sign (@) character, followed by the number of bytes (in decimal) in the argument list. Therefore, the function declared as
   int func( int a, double b )
is decorated as
  _func@12
Case-translation convention None

The /Gz compiler options specifies __stdcall for all functions not explicitly declared with a different calling convention.

The __cdecl calling convention

The __cdecl calling convention is used for the SilverCExec function, and also for SilverC library functions, which are called via pointers passed to the DLL. The calling function cleans up the stack Functions that use this calling convention require a function prototype. The following list shows the implementation of this calling convention.

Element Implementation
Argument-passing order Right to left
Argument-passing convention By value, unless a pointer or reference type is passed
Stack-maintenance responsibility Called function pops its own arguments from the stack
Name-decoration convention An underscore (_) is prefixed to the name. Therefore, the function declared as
   int func( int a, double b )
is decorated as
    _func
Case-translation convention None

The /Gd compiler options specifies __cdecl for all functions not explicitly declared with a different calling convention.

Note that although for __cdecl functions the C compiler generates a symbol that is prefixed with ‘_’, the linker, when exporting such a symbol from the DLL, strips the ‘_’ from the exported name.

You may use a function with a name other name than DllMain by using the /ENTRY: linker option; to keep things simple, we retain the DllMain convention.

The Silver Engine is built using the _AFXDLL architecture, that is, it uses the MFC and C runtime DLL's, rather than statically linking them. The SilverC extension DLL may also use the MFC as well in a DLL, thus saving code. Beware... the standard run-time library calls in a SilverC extension library are actually implemented via call through a function pointer in the SSREX structure passed at initialization time.

Building SilverC DLLs Using the MFC Wizard

(using Microsoft Visual C++ version 6.0)

Files Used in the Project

Silver directory

silver.h SilverC include file
ssnodes.h SilverC include file
ssrex.h SilverC include file
rexcodes.h SilverC include file
silver2.h SilverC include file
sskeys.h SilverC include file

Execution directory

dllsamp.c SilverC driver program
dllsamp.h defines user codes for SilverCExec operations

Project directory

SSDLL.cpp MFC generated main file
SSSDLL.h MFC generated header
SSSDLL.rc MFC generated resource file
SSSDLL.def MFC generated DEF file
resource.h MFC generated define file for resources
StdAfx.cpp MFC generated file for standard system includes
StdAfx.h MFC generated include file for standard system includes
winhead.h file used to make SilverC and Windows definitions coexist;either include it in SILVER2.H or make another file to include WINHEAD.H and SILVER2.H together.
Subclass.cpp file containing SilverCExec and window subclassing code

Generating the DLL Skeleton

The following procedure may be used to build a DLL that may be used by a SilverC program.

  • Select File and New from the menu, and select "Project Workspace" from the list
     
  • From New Project Workspace dialog, select "MFC AppWizard (dll)", and give the project a name and select a directory (preferably empty) to put it in. In this case, the project is titled "SilverDLL"
     
  • From the MFC AppWizard dialog, select "regular DLL using shared MFC DLL", and choose any other options (OLE Automation, Windows Sockets, Add comments). The new project will be created.
     
  • Edit the main file in your new project: it will have the same name as your project, with the extension ".cpp". In this case, "SSDLL.cpp". The file will contain the code to declare and initialize an object derived from the MFC CWinApp class, its name derived from the name of your project, in this case CSSDLLApp. If you wish to add code that executes when the DLL loads or exits, you may override the class functions InitInstance and ExitInstance, respectively.
     
  • The following will need to be added to the project to allow SilverC to load and initialize your DLL:
    • A declaration for the table of SilverC library functions:
           SSREX *sc;
    • The file SSREX.H will be needed to define the SSREX structure; the file SILVER2.H may be used, which includes SSREX.H
    • The exported function SilverCExec, which is used by the Silver DLL loader to initialize the DLL for SilverC purposes, and also may be used by the SilverC program as a gateway to invoking DLL functionality.
  • In order to force the Visual C++ compiler to search for include files in the proper order, we recommend that you check the "Ignore standard include paths" box, and set the Additional Include Paths as follows: (Project Settings dialog, C/C++ tab, Preprocessor category)
  •       c:\msdev\include,c:\msdev\mfc\include,c:\silver,c:\silver\ex

  • you may want to generate the DLL directly into the Silver directory or the directory containing your SilverC source code: Project Settings dialog, choose Link tab, and the General category, Output Directory entry
     
  • to facilitate debugging, you may set the executable by: Project Settings dialog, Debug tab, General category: set executable to engine.exe in the SILVER directory and change the working directory to the SILVER directory

Using the REX Interface with Windows DLLs

int rex_load( char *rex_name );
int rex_exec( int handle, int operation, void *data );
int rex_unload( int handle );

The REX interface was designed to allow a Silver C program to load binary code files under DOS, REX being the name for Relocatable EXecutable file format. The REX functions are overloaded under Windows for use with DLLs, to much the same effect. The REX functions will only load REX files under DOS and DLL files under Windows, and not vice-versa. They are documented in the SilverScreen API Reference manual manual.

A Note on Resources

An important usage of 3rd-party DLL’s is to store your own resources (dialog templates, menus, toolbars and the like) for your own UI. A requirement of using the MFC resource handling mechanisms to load resources from the DLL is that the default resource handle for the application be set to the instance of the DLL. The call to set the default resource handle is the MFC function AfxSetResourceHandle, passing it the instance handle of your resource DLL. The instance handle is used to uniquely identify an executable module (.EXE or .DLL), and is set when your DLL is loaded. If you have an MFC style DLL, then it is part of the CWinApp-derived class that is the base of your DLL. Alternatively, if you have an "old-style" DLL, the instance handle is passed as the first argument to DLLMain.

Most often, you can set the default resource handle early in your DLL initialization code, and forget about it. For purposes of loading its own resources, SilverScreen will set the default resource handle as necessary, and then restore it when finished. This is always true in the case of executed commands (a la ss_command), however, it is possible that we have missed cases where the resource handle is not set and restored properly, most likely in cases of SilverC function calls. If you run into a situation where you suspect that this is the case (i.e., a resource in your DLL is not loaded properly), then please let us know. Note that SilverScreen will restore the proper instance handle when your program exits, so it is safe to leave it unrestored in your DLL.

Originally, we recommended wrapping each and every call to load resources with code to set and restore the default resource handle, but that is not necessary now, and was awkward to do in certain cases where MFC needed to load resources from the DLL without explicitly notifying the program. By leaving the resource handle set to that of the DLL, things like tooltips can be retrieved properly by MFC.

DLL Debugging Techniques

DLLs built for SilverScreen may be debugged using the Visual C++ debugger. You must build your DLL for debug, and use the debug version of the SilverScreen engine (\silver\debug\engine.exe). Set breakpoints in your code, as usual, and set the Executable program to engine.exe (pathed appropriately) by selecting the Project Settings dialog, Debug tab, General category; you should also set the working directory here, as well.

A Note on Command IDs

In your DLL, when you are setting up command IDs for menu items, toolbar buttons and the like, the range ID_FIRST_DEVELOPER_ID through ID_LAST_DEVELOPER_ID (defined in silver.h) should be used. If you don't use IDs in this range, then MFC will think that there is no handler for them, and will disable them, probably not what you want.

SilverScreen now has two ways of dealing with developer command IDs. In the first case (the default), SilverScreen will automatically inform MFC that there are handlers for these commands, and thus they will be enabled when you use them.

In the second case, SilverScreen can be told to pass the address of a CCmdUi object for the command ID down to the DLL, and the DLL can determine what is to be done. This behavior is conditioned on the CV variable CV_PASSTHRU_CMDUI_ENABLE. When set to TRUE, SilverScreen will, in its command UI handler for developer's ids, call SendMessage with a message value of WM_CMDUI_ENABLE, a wParam value of the command ID, and lParam is the address of the CCmdUi object passed to SilverScreen. This message may then be intercepted in your subclassing window function, and the CCmdUi pointer used to call Enable, SetCheck or othe member functions.

For example, in your initialization code, you would call:

cv_set( CV_PASSTHRU_CMDUI_ENABLE, 1 ); // enable command ID passthrough to DLL

Then, in your mainframe subclassing code, you would add the something like following code:

switch ( message )
   {
   …
   case WM_CMDUI_ENABLE:
        {
        int enable;
        // obtain CCmdUi pointer
        CCmdUI *cmdui = (CCmdUI *) lParam;
        // is command       enabled??
        enable = get_command_enable_value( wParam );
        // call Enable with appropriate value
        cmdui->Enable( enable );
        }
   break;
   …
   }

Window Subclassing

In Windows, the technique of window subclassing is used to intercept and perhaps filter Windows messages before they arrive at a particular window. When you subclass a Windows window, you are placing a new window procedure at the head of a chain window procedures for that window. In SilverScreen, we have designed our internal architecture so that the main frame and view windows may be subclassed safely by the DLL developer. Since Windows menus and toolbars generate WM_COMMANDs, and the only way to get your hands on what WM_COMMANDs are generated is to receive them in a window procedure, you will very likely wish do this subclassing. The MFDLL project included in the developer's engine distribution provides an example of how to go about subclassing both the main frame and the view windows. Exhibits 4 though 6 show how this subclassing is effected in SilverScreen.

SilverScreen Architecture

SilverScreen and MFC

SilverScreen is built as an MFC document/view application, using SDI (Single Document Interface). This means that there SilverScreen contains a main frame window implemented by a class derived from CFrameWnd, and a single view window derived from CView. The main frame window contains the usual assortment of user interface items, including a main menu, toolbars and status bar. The view window is where SilverScreen drawings are displayed. Exhibit 3 shows the gross structure of SilverScreen's architecture.

SilverScreen frame window/view window architecture

Exhibit 3. SilverScreen frame window/view window architecture

In subclassing SilverScreen, the windows that we are interested in are the main frame windows and the view window. In order to subclass them, we must have their window handles. The main frame window handle may be obtained by calling the MFC function AfxFrameWnd to obtain a CFrameWnd pointer, and then calling the CFrameWnd's member function GetSafeHwnd. The return value is the main frame window handle. The view window handle maybe obtained by calling the CFrameWnd member function GetViewWindow to obtain a CView pointer, and then calling its GetSafeWnd member function. The following piece of code demonstrates the technique.

void GetFrameAndViewWindowHandles()
{
CFrameWnd *mf;
CView *v;
HWND frame_handle = 0;
HWND view_handle = 0;

if ( mf = (CFrameWnd *) AfxGetMainWnd() )
   {
   frame_handle = mf->GetSafeHwnd();
   if ( v = mf->GetActiveView() )
      view_handle = v->GetSafeHwnd();
   }
}

SilverScreen Input Processing

Most MFC applications use the default MFC message processing mechanisms to allow messages to be routed to appropriate handler classes. However SilverScreen has a number of sitations where it is necessary to use a modal-style inchar function to control input. This same inchar is the same as is used in the SilverC library.The following diagrams illustrate the relationship between a standard MFC application (Exhibit 4), SilverScreen in standalone usage (Exhibit 5), and SilverScreen with a subclassing DLL (Exhibit 6). Note that the subclassing typically pertains to that of SilverScreen’s main frame and view windows.

Normal MFC Event Flow

Exhibit 4. Normal MFC Event Flow

Exhibit 4 shows the default flow of events through a normal MFC application. The MFC application MessagePump routing causes application events to be dispatched to the MFC window procedure, and from there they are routed out to the appropriate MFC class objects.

SilverScreen Event Flow

Exhibit 5. SilverScreen Event Flow

Exhibit 5 shows how the situation exists in SilverScreen when running in standalone mode. Because SilverScreen needs to implement modal-style inchar routing, both for its internal use, and for use in SilverC programs, the normal flow of messages is changed by subclassing the main frame and the view windows, passing the messages through the SilverScreen window procedure. When inchar is called, the SilverScreen window procedure picks out messages that are appropriate for returning via inchar, and sends them off that way. Other messages are passed through to MFC as normal. When inchar is not called, then message flow proceeds as before. Note that in this situation, when inchar is called, some messages are passed to MFC as well as returned via inchar, while others are not passed down to MFC.

SilverScreen Event Flow with DLL Subclassing

Exhibit 6. SilverScreen Event Flow with DLL Subclassing

Exhibit 6 shows the situation when the DLL developer subclasses the main frame and view windows. The DLL window procedure is inserted in the subclass chain before the SilverScreen window procedure. Any messages that pass through the DLL window procedure may be filtered off by not calling the next handler in the chain; or modified by changing the parameters passed to the next message handler, or ignored altogether.

The WM_FEED_CHAR Message

One of the facilities available when subclassing is the ability to pass a message through to be returned via inchar in a SilverC program. Because the DLL window procedure is at the head of the event handling chain, it may fabricate messages and then pass them along to the SilverScreen window procedure. If the message is WM_FEED_CHAR (from silver.h) then the wParam associated with it is passed though to inchar. This is demonstrated in MFDLL, where the IDM_FILE_EXIT command is changed into a WM_FEED_CHAR message with wparam of ESCAPE. The wparam of a WM_FEED_CHAR message is passed through to inchar without translation, so in effect an ESCAPE keystroke is returned to the SilverC program that called inchar. You need not use a predefined keystroke or mouse event with WM_FEED_CHAR, any value will be returned uninterpreted.

The DLL Developer Problem Solver

Displaying Menu Text on the Status Line

In a normal Windows application, the text associated with a menu item is displayed on the status line. In a DLL, if you have put up your own menu, the link between the menu and the status line is broken. The solution is to intercept the WM_MENUSELECT message in your subclassed window function. The wParam parameter specifies the command ID desired. Fetch the appropriate text for that command ID, and display it on the status line by using qmessage.

Handling CmdUI for Developer IDs

For the range of command IDs between ID_FIRST_DEVELOPER_ID and ID_LAST_DEVELOPER_ID, the default SilverScreen behavior is to enable them automatically. If you desire a different behavior, then handle the WM_CMDUI_ENABLE (0x402) message in your subclassed window procedure. The wParam parameter is the command ID, and the lParam parameter is the address of a CCmdUi object. The CCmdUi object may then be used to call Enable, or SetCheck, or whatever. This is more fully described in the section A Note on Command IDs above.

Changing the Mouser Cursor Shape

In a DLL, there are two ways that you can change the shape of the mouse cursor. One way is to set the view window's class cursor to the handle of the cursor you want to use. The other is to set the view window's class cursor field to NULL, and trap the WM_MOUSEMOVE command in your subclassing window procedure, and calling SetCursor with the handle of your desired cursor there.

An example of the first approach:

   static HCURSOR view_cursor=0;  // to save old view
                                  // window class cursor
   extern HINSTANCE dll_instance; // DLL instance handle
  
   void SetMouseCursor()
   {
   HWND hwnd;
  
   if ( hwnd = GetViewHwnd() ) // obtain the view window's handle
      {
      HCURSOR cursor =
      LoadCursor(dll_instance,MAKEINTRESOURCE(IDC_DLLCURSOR));
      view_cursor =
      (HCURSOR) SetClassLong(hwnd,GCL_HCURSOR,DWORD)NewCursor);
      }
   }

An example of the second approach. First, set the view window's class cursor to NULL:

   static HCURSOR view_cursor=0;  // to save old view
                                  // window class cursor
   extern HINSTANCE dll_instance; // DLL instance handle
  
   void SetMouseCursor()
   {
   HWND hwnd;
  
   if ( hwnd = GetViewHwnd() ) // obtain the view window's handle
      {
      view_cursor =
        (HCURSOR) SetClassLong(hwnd,GCL_HCURSOR,(DWORD)NULL);
      }
   }

Then, in the subclassing window procedure:

   static HCURSOR myCursor = 0;
   extern HINSTANCE dll_instance;
   …
   switch ( message )
      {
      …
      case WM_MOUSEMOVE:
         {
         if ( ! myCursor )
            LoadCursor( dll_instance,
                        MAKEINTRESOURCE(IDC_DLLCURSOR) );
         SetCursor( myCursor );
         }
      break;
      …
      }

Remember. If you change the view window's class cursor, you must set it back before returning to SilverScreen.

Calling C++ from C

Occasionally you will find yourself in a position, particularly if you are porting older C code, where it would be convenient, if not necessary, to call a C++ routine from C code. A legal and portable way to do this is to define a C++ function with a C interface (note that this must be a global function, and not a member function). Such a function is defined in a .cpp file (C++ source) and declared using the extern "C" mechanism. This makes the function appear to be C-callable, but inside the function, you may make use of an C++ constructs that you wish. The function may only take C-style parameters (no classes, class pointers, references, etc.).

For example, suppose that you wish to call C++ function cpp_func from a .C file (C source). Then the technique is to define the function in a C++ file, but declare it in such a way that it has "C" interface. The following is an example:

HEADER.H

Contains the declaration for cpp_func. Note how the extern "C" mechanism is wrapped by ifdefs that allow the extern "C" to be seen by the C++ compiler (since __cplusplus is only defined in a C++ compiler), but not by a C compiler (where it not a legal C construct).

   #if defined(__cplusplus)
   extern "C"
   {
   #endif
   int cpp_func( void )
   #if defined(__cplusplus)
   }
   #endif

CPPFILE.CPP

By including HEADER.H, the cpp_func function is known to the C++ compiler to have a C interface.

   …
   #include "header.h"
   …
   int cpp_func( void )
   {
   …
   }
   …

CFILE.C

Using HEADER.H, the cpp_func is declared for use.

   #include "header.h"
   …
   int i;
   i = cpp_func();
   …

 

Sample Projects

When you install the SilverPlus development kit, a number of sample projects are installed.

In the following descriptions, the term <silver> refers to the directory where SilverScreen is installed.

SCDLL

The SCDLL project is intended to demonstrate simple invocation of dialogs using a DLL. The DllMain version of the DLL is used.

The SilverC driver file for the SCDLL project is DLLTEST.C.

Installed into: <silver>\Samples\SilverPlus\SCDLL

MFDLL

The MFDLL project is intended to demonstrate various techniques useful in DLL development:

  • subclassing the view and mainframe windows
  • Use of CWinApp-derived class for DLLs
  • Command UI handling
  • Various UI techniques, including context menus, toolbars and dialogs
  • Script windows

The SilverC driver file for the MFDLL project is MFDLL.C.

Installed into: <silver>\Samples\SilverPlus\MFDLL

ScriptWin

The ScriptWin project is intended to demonstrate use of the script window API, for displaying SilverScreen drawings in arbitrary windows.

The SilverC driver program for the ScriptWin project is ScriptWin.c

Installed into: <silver>\Samples\SilverPlus\Scriptwin

Preview

The Preview project is intended to demonstrate a print preview interface implemented in a DLL.

Installed into: <silver>\Samples\SilverPlus\Preview

DLLStuff

This is not really a project, but is rather set of code templates that you can use on which to base your applications.

Installed into: <silver>\\DLLStuff

 

 

Copyright

Copyright 1997-1999 by Schroff Development Corporation, Shawnee-Mission, Kansas, United States of America. All rights reserved. 

Disclaimer of All Warranties and Liability

Schroff Development Corporation makes no warranties, either express or implied, with respect to this document or with respect to the hardware and software described in this document. Schroff Development Corporation does not guarantee, warrant or make any representation regarding the use of, or the results of the use of the information in terms of correctness, accuracy, reliability, or performance. Schroff Development Corporation assumes no liability for any direct, indirect, or consequential, special or exemplary damages, regardless of its having been advised of the possibility of such damage.