NOVELL TECHNICAL INFORMATION DOCUMENT TITLE: AppWare Bullets Article (3/94) Source Code DOCUMENT ID: TID100120 DOCUMENT REVISION: A DATE: 05APR94 ALERT STATUS: Yellow INFORMATION TYPE: Symptom Solution README FOR: APINST.EXE NOVELL PRODUCT and VERSION: AppWare Foundation for Windows 1.70 ABSTRACT: APINST.EXE contains the source code and the executable for the PDS Bullets article that was published in March 1994. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ DISCLAIMER THE ORIGIN OF THIS INFORMATION MAY BE INTERNAL OR EXTERNAL TO NOVELL. NOVELL MAKES EVERY EFFORT WITHIN ITS MEANS TO VERIFY THIS INFORMATION. HOWEVER, THE INFORMATION PROVIDED IN THIS DOCUMENT IS FOR YOUR INFORMATION ONLY. NOVELL MAKES NO EXPLICIT OR IMPLIED CLAIMS TO THE VALIDITY OF THIS INFORMATION. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ SYMPTOM Users wanted the source code and the executable for the PDS Bullets article that was published in March 1994. SOLUTION APINST.EXE contains the source code and the executable for the PDS Bullets article that was published in March 1994. Self-Extracting File Name: APINST.EXE Revision: A Files Included Size Date Time \ APINST.TXT (This File) APPF.R 4244 03-17-94 11:49a MAIN.C 9353 03-17-94 12:49p MAIN.H 2023 03-16-94 9:30a MAIN.I 73668 03-17-94 11:57a MAIN.R 579 02-16-94 3:02p MAIN.Z 2465 03-17-94 12:49p APP.EXE 25128 03-17-94 12:50p APP.ICO 766 09-17-93 12:00a MAIN.RC 2095 02-16-94 9:40a MAINR.H 2943 03-16-94 9:30a MAIN.BMK 2611 03-17-94 12:55p MAIN.DEF 414 02-11-94 5:41p MAIN.RES 1304 03-17-94 12:50p DISCLAIM.TXT 977 07-15-91 12:30p Installation Instructions: No installation instructions are included with this file. Solution Specifics: The following the text of the Bullets article: "Loading the Application Instance as a Resource" AppWare Foundation: Loading the Application Instance as a Resource The Novell AppWare Foundation (NAWF) is the base component of the Novell AppWare development architecture and is designed for developers who want to code directly to the core component of the AppWare development environment. NAWF is composed of programming libraries and a cross-platform API for accessing operating system, user interface, and connectivity services with traditional 3GL programming tools. NAWF is divided into different components and the components are grouped into series. Currently there are three series: * Operating System * User Interface * Network Connectivity. The components are a collection of utility routines that are reusable within and among applications. Components encapsulate their routines with associated data elements, and some components rely on and inherit capabilities from other components. These components are implemented as modules using C. This article introduces the experienced C programmer to NAWF by detailing a method for creating a generic NAWF application that loads the Application instance as a resource. This resource can be used as a seed for other NAWF applications. Instances Instances are complex entities with many characteristics and behaviors. Instances are designed as general purpose entities, however all instance-using NAWF components are from the User Interface Series and are used to implement graphical user interfaces. They usually have a visible representation on the screen and interact with the end-user. The characteristics of instances include their types, attributes, and relationships to one another. Instances can be created in two ways: * By loading instance data into a structure invoking the NAWF UInstCreate() function * By describing it in a NAWF superset resource file, compiling it using the NAWFresource and compiler, and calling the UInstLoad() function. This article demonstrateshow to load the Application instance as a resource. As instances are created, they are organized into a hierarchy. At the top of every instance hierarchy there is an Application instance. Having a generic NAWF application you can later use as a starting point for other applications eases the process of adding functionality. If you can load a simple NAWF application as a resource, it will be easy to port that application to all other target operating system platforms. Since the Application instance is just another NAWF instance, you can edit it using a resource editor. For example, you could set the Application instance style to "iconized" by changing the attribute in the resource definition. To do this, you do not have to recompile the C source modules. The change can be effected by recompiling only the resources and then relinking the program. Elements of a Generic NAWF Application Four types of files comprise a generic NAWF application: * C Sources (.C) * Header (.H) * Intermediate include file (.Z) * Superset resource file (.R) Intermediate include files have a .Z extension and may include any number of .h header files. All headers to be pre-compiled are gathered into the .Z file. Intermediate include files are used only for source files that are intended to be machine independent. Superset resource files have a .R file extension. Superset resources are resources defined by a platform-independent resource definition language. This language allows you to specify instance information that is a superset of the resource information for all platforms. Superset instance resources are described in text form in a resource data file. The instance resource contains a standard header followed by fields specific to the instance type. Loading the Application instance as a resource requires four steps: * Defining the application instance in the superset resource file * Making the NAWF component initializations in the C source file * Defining the appropriate vectors in the C source file * Loading the Application instance Defining the Application Instance The Application instance is just another NAWF instance. Like all instances, the application instance has common instance information and specialized instance information. The code segment in Figure 1 defines the Application instance in the superset resource file. ***************************************************************** Figure 1: Defining the Application instance in superset resource file resource URES_TYPE_INSTANCE(APP_ID_KEY) { /* options, native ref, default font, device type, extra */ UR_UNITS_CHARS | UR_RECT_FRAME, DataNone{}, DataNone {}, N_NULL, {}, { InstApplication { /* native key, resource options, childcount */ 0, UR_RECT_CONTENT, 0, /* action code, action params, user data, buf size, buf data */ N_NULL, DataNone {}, N_NULL, 0, DataNone {}, /* Filter */ Filt {UINST_FOPT_VECTOR | UINST_FOPT_ALL, { N_NULL, N_NULL, N_NULL }, { N_NULL, N_NULL, N_NULL }, "AppVector" }, /* item type, data, attrs */ TypeID{UITEM_ID_BASEFONT}, DataStr{ "App Instance" }, AttrsNone{}, /* Virtual Data */ VirtNone{}, /* style, style2, options, options2, alignment */ UINST_STYLE_SHOW|UINST_STYLE_CLOSEABLE| UINST_STYLE_ICONIZEABLE|UINST_STYLE_SIZEABLE, N_NULL, N_NULL, N_NULL, N_NULL, /* frame, selection, mnemonic, cursor */ RectNone , SelNone {}, MnNone {}, DataStd {URES_STD_ARROW_CURS}, /* help desc, help topic, extra */ HelpNone{}, HelpNone{}, {}, /* icon, menu bar, window menu position, size information */ DataNone {}, DataRef {"",URES_TYPE_INSTANCE, APP_MENU, N_NULL}, N_NULL, SizeNone {}, /* foreground timer intervals, background timer intervals, help config structure, extra */ 0, 0, HelpConfigNone {}, {} }, } }; END of FIGURE 1 ***************************************************************** Initializing NAWF Components An important part of the application setup process is initializing each NAWF component that will be used in the application. NAWF components must be initialized in a strict order to be properly utilized by an application. Failure to observe this requirement can cause erratic application behavior such as a General Protection Fault in the NAWF.DLL under MS Windows. The components listed in Figure 2 are shown in the proper sequence. Although only three components are listed, other components must be initialized in proper order, depending on which ones you use in your application. ***************************************************************** Figure 2: NAWF component initialization /* Essential foundation components */ if (! UModInit ( &Access, UMOD_VERSION, 0L )) UModExit( UErrGetVal( &Access ) ); if (! UMemInit ( &Access, UMEM_VERSION, 0L )) UModExit( UErrGetVal( &Access ) ); if (! UErrInit ( &Access, UERR_VERSION, 0L )) UModExit( UErrGetVal( &Access ) ); /* Other component initializations */ END of FIGURE 2 ***************************************************************** Defining Message Vectors Before loading the Application instance, you must make sure that the appropriate vectors are defined for the messages that you want to filter. Using vectors for message filtering is somewhat different than using callback filters and explicit filter masks. Rather than writing a single message filter procedure that handles all message types utilizing a switch statement, you can write a set of individual message handlers. Each handler can be written to handle a specific message before or after notification (pre- or post-notification). These handlers are then associated with message types by a vector definition, shown in Figure 3. Note: UInstVectorBegin, UInstVectorMsg, and UInstVectorEnd are macros with parameters which generate code. These macros must never be terminated with semicolons. ***************************************************************** Figure 3: Associating message types with a vector definition /* Begin the vector definition */ UInstVectorBegin( AppVector, N_NULL ) /* Associate OnAppAfterCREATE filter procedure with the post-filtered UMSG_CREATE message */ UInstVectorMsg( UMSG_CREATE, UMSG_MODE_AFTER, OnAppAfterCREATE) /* Associate OnAppAfterACTION filter procedure with the post-filtered UMSG_ACTION message */ UInstVectorMsg( UMSG_ACTION, UMSG_MODE_AFTER, OnAppAfterACTION) /* End the AppVector definition */ UInstVectorEnd( AppVector ) END of FIGURE 3 ***************************************************************** The code in Figure 3 associates two filter procedures with the UMSG_CREATE and the UMSG_ACTION messages. The code segment in Figure 4 defines the OnAppAfterCREATE filter procedure that would automatically be called when a post-filtered UMSG_CREATE message is generated. ***************************************************************** Figure 4: Defining the OnAppAfterCREATE filter procedure N_GLOBAL_FUNC( nbool8 ) OnAppAfterCREATE ( pUMsgStruct pMsg ) { /* You can put in the code that you want executed */ return N_TRUE; } END of FIGURE 4 ***************************************************************** Loading the Application Instance NAWF instances can either be created by calling UInstCreate(), or by loading it as a resource by a call to the function UInstLoad(), as shown below. nid UInstLoad (pAccess, idInstParent, idResPack, pInstFilter, userLoadData); UInstLoad() is used to load an instance or an instance hierarchy from a resource definition. The example program discussed in this article uses the UInstLoad() function to load the Application instance as a resource. The code segment below demonstrates how the Application instance must be defined in the superset resource (.R) file. Assuming that you have performed the appropriate NAWF component intializations, and have created the UModMain() function with the message loop, you can add the function shown in Figure 5 to load the Application instance as a resource. ***************************************************************** Figure 5: Loading the Application instance N_INTERN_FUNC( nid ) LoadApp( void ) { nid idResPack, appID; /* Open resource file */ /* Access and idResFile are global variables */ idResFile = UResOpenModule( &Access, UModGetModule( &Access ), URES_OPEN_READ ); /* Initialize Application instance */ idResPack = UResCreatePack (&Access, idResFile, URES_TYPE_INSTANCE, APP_ID_KEY, URES_PACK_NO_KEEP); DEBUG_ASSERT( UErrGetVal( &Access ) == N_SUCCESS && UResValidatePack( &Access, idResPack ), "Can't reference App resource" ); /* Load the App instance from the resources */ appID = UInstLoad (&Access, N_NULL, idResPack, N_NULL, N_NULL); return (appID); } END of FIGURE 5 ***************************************************************** Using a graphical resource editor, you can easily add additional NAWF instances as "children" of the Application instance. These instances are defined wholly in the resource file and only processing code need be added to your program. If you would like to obtain the complete source code for the example discussed in this article, it is available for downloading from Novell's NOVLIB forum on CompuServe (Library 7, APINST.EXE). If you have additional questions about any of the concepts discussed in this article or about the Novell AppWare Foundation, please contact Novell at 1-800-NETWARE (1-800-638-9273) or 1-801-429-5588. ***************************************************************** ***************************************************************** (c) Copyright 1994 Novell, Inc. This article originally appeared in Novell Professional Developer Bullets, Volume 6, Number 3. ***************************************************************** ***************************************************************** ÿ