Main Page
    Cookbook/Overview     ImageMeister     the jcprops file     Licensing
    Binary Installation & Configuration [ Win · Mac · Nix · OSX ]     Changes
    Public API
    Source Code Main Page
        Java [ Common · Win · Mac · Nix ]     Native Code [ Common · Win · Mac · Nix ]     Manifest
        Native Code Overviews [ Common · Win · Mac · Nix · Strings ]     Macros [ General · Native Macros ]
        Walkthroughs [ Java only · Java and native ]     Building [ Win · Mac · Nix · OSX ]     Distribution Issues

Walkthrough: FileRegistry.getMainMonitor()

This file walks through a call to the Java and native sides of JConfig.

This file traces the steps when you call the FileRegistry.getMainMonitor() method.

Let's assume that we're running on Windows95 with the SunJDK. This will use the jcnfigSN.dll, and we'll assume that this DLL was compiled with the DO_SEH symbol defined (this indicates that each native method should be surrounded by a SEH frame.)

The sequence of routines which will be called are shown, followed by a description of each step.


Step 1.


    public static Monitor getMainMonitor() {
        Monitor	    retMon = null;

        if ( delegate != null )
            retMon = delegate.getMainMonitor();

        if ( retMon == null )	    
            retMon = new MonitorPlain();

        return retMon;
    }
from FileRegistry.java
If delegate isn't null, it calls the delegate to obtain the user's main monitor. If this return null, or if delegate is null it returns a 'plain' monitor object. This will be initialized using the built-in Java information, which is minimal, and consists only of the width and height of the main monitor.

We'll assume that delegate is not null.


Step 2.

                                                                              `

    public Monitor getMainMonitor() {
        return MonitorHelperMSVM.getMainMonitor();
    }
from FileRegistryMSVM.java
In the current case, the delegate is a 'FileRegistryMSVM' object, which just passes the call to a static method of the 'MonitorHelperMSVM' class.

For a description of how the FileRegistryMSVM object was selected as the delegate, see the overview_init.html file.


Step 3.


    static Monitor getMainMonitor() {
        int         monitorData[], theErr;

        monitorData = new int[ AppUtilsMSVM.kMonitorInfoNumInts ];

        theErr = AppUtilsMSVM.getMainMonitorInfo( monitorData );

        if ( theErr != ErrCodes.kNoErr )
            return null;

        return new MonitorMSVM( monitorData, 0, AppUtilsMSVM.kMonitorInfoNumInts );
    }
from MonitorHelperMSVM.java
The 'MonitorHelperMSVM.getMainMonitor()' method creates an int array, and passes it to a native method. The native method will fill out this int array with information on the main monitor. For instance, the top of the main monitor will be placed at offset 0 of the int array, the left of the monitor at offset 1, etc. Which data is stored where is defined by the 'kOffs...' constants in the 'MonitorMSVM' class.

Creation of the 'MonitorMSVM' object will be described below.


Step 4.


    static int getMainMonitorInfo( int monitorInfo[] ) {
        return nativeGetMainMonitorInfo( monitorInfo );
    }
    private static native int nativeGetMainMonitorInfo( int monitorInfo[] );
from AppUtilsMSVM.java
'MonitorHelperMSVM' calls 'AppUtilsMSVM.getMainMonitorInfo()' with an array of ints. This method is just a wrapper around the native method 'AppUtilsMSVM.nativeGetMainMonitorInfo()'.


Step 5.


    SEH_EXP JINT SEH_FUNC( jconfig, AppUtilsMSVM, nativeGetMainMonitorInfo ),
    JINTARRAY pMonitorInfo )
    {
        SEH_TRY {
            return CALL_INNER( nativeGetMainMonitorInfo )( INNER_PREFIX, pMonitorInfo );
        }
        SEH_EXCEPT( _TXL( "SEH in nativeGetMainMonitorInfo\n" ) )
    }
from sehstubs.cpp
Now, we're in native code. This is a stub routine, which installs an SEH frame, and calls the routine 'INNER_nativeGetMainMonitorInfo' (see below.) All native methods follow the same pattern.

If we replace the SEH-related macros, this looks like:


    JNIEXPORT JINT JNICALL Java_COM_tolstoy_jconfig_win_AppUtilsMSVM_nativeGetMainMonitorInfo(
    JNIEnv *pEnv,
    jclass pObj,
    JINTARRAY pMonitorInfo )
    {
        __try {
            return INNER_nativeGetMainMonitorInfo( pEnv, pObj, pMonitorInfo );
        }
        __except ( EXCEPTION_EXECUTE_HANDLER ) {
            Debugger::debug( __LINE__, _TXL( "SEH in nativeGetMainMonitorInfo\n" ) );
            return kErrSEH;
        }
    }
from sehstubs.cpp
'JINT' and 'JINTARRAY' are native macros; see nativemacros.html for more information.
'JNIEXPORT' and 'JNICALL' are defined by JNI.


Step 6.


    EXP JINT FUNC( jconfig, AppUtilsMSVM, nativeGetMainMonitorInfo ),
    JINTARRAY pMonitorInfo )
    {
        long            *monitorInfoP, theErr;

        BEGINTRY {
            CHECKSIZE( pMonitorInfo, SMonitors::kMonitorInfoNumInts );
        
            monitorInfoP = LOCKINTARRAY( pMonitorInfo );
        
            theErr = SMonitors::iGetMainMonitorInfo( monitorInfoP );
        
            UNLOCKINTARRAY( pMonitorInfo, monitorInfoP );
        }
        ENDTRY

    bail:

        return theErr;
    }
from AppUtilsMSVM.cpp
This routine is called by the previous routine which installed the SEH frame. If we replace the macros in this routine, it looks like:

    jint INNER_nativeGetMainMonitorInfo,
    JNIEnv *pEnv,
    jclass pObj,
    jintArray pMonitorInfo )
    {
        long            *monitorInfoP, theErr;

        try {
            {	//	this was the CHECKSIZE macro
                if ( ( (pMonitorInfo) == NULL ) ||
                        ( pEnv->GetArrayLength( (pMonitorInfo) ) < (SMonitors::kMonitorInfoNumInts) ) )
                    {
                        theErr = kErrParamErr;
                        goto bail;
                    }
            }
        
                // this was the LOCKINTARRAY macro
            monitorInfoP = pEnv->GetIntArrayElements( (pMonitorInfo), 0 );
        
            theErr = SMonitors::iGetMainMonitorInfo( monitorInfoP );
        
                //	this was the UNLOCKINTARRAY macro
            pEnv->ReleaseIntArrayElements( (pMonitorInfo), (monitorInfoP), 0 );
        }
        catch ( const LPCTSTR msg ) {
            Debugger::debug( __LINE__, _TXL( "got exception" ), msg );
            theErr = kException;
        }

    bail:

        return theErr;
    }
from AppUtilsMSVM.cpp
First, this checks that the parameter is OK. Then, it looks the array of Java ints, and calls a static method in the SMonitors class. If an exception occurs, it prints it out. After returning from SMonitors, it unlocks the Java int array, and returns a error code.


Step 7.


    long SMonitors::iGetMainMonitorInfo( long *monitorInfoP )
    {
        HWND            hDesk;
        HDC             hDC;
        RECT            rcWorkarea, rcBounds;
        long            theErr, screenWidth, screenHeight, screenDepth;
        BOOL            bRet;

        theErr = kErrNoErr;

        bRet = SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWorkarea, 0 );
        if ( !bRet ) {
            theErr = kErrSystemParametersInfo;
            goto bail;
        }

        screenWidth = GetSystemMetrics( SM_CXSCREEN );
        screenHeight = GetSystemMetrics( SM_CYSCREEN );
        SetRect( &rcBounds, 0, 0, screenWidth, screenHeight );
    
        hDesk = GetDesktopWindow();
        hDC = GetDC( hDesk );
        screenDepth = GetDeviceCaps( hDC, BITSPIXEL );
        ReleaseDC( hDesk, hDC );
    
        stuffMonitorInfo( &rcBounds, &rcWorkarea, screenDepth, TRUE, 0, monitorInfoP );

    bail:

        return theErr;
    }
from SMonitors.cpp
This gets information on the user's main monitor, and then puts it into the appropriate locations of an int array.

    MonitorMSVM( int data[], int dataOffset, int dataLen ) {
        int         top, left, bot, right;

        top = data[ dataOffset + kOffsBoundsTop ];
        left = data[ dataOffset + kOffsBoundsLeft ];
        bot = data[ dataOffset + kOffsBoundsBottom ];
        right = data[ dataOffset + kOffsBoundsRight ];
        boundsRect = new Rectangle( left, top, right - left, bot - top );

        top = data[ dataOffset + kOffsWorkareaTop ];
        left = data[ dataOffset + kOffsWorkareaLeft ];
        bot = data[ dataOffset + kOffsWorkareaBottom ];
        right = data[ dataOffset + kOffsWorkareaRight ];
        workareaRect = new Rectangle( left, top, right - left, bot - top );

        depth = data[ dataOffset + kOffsDepth ];
        refNum = data[ dataOffset + kOffsRefNum ];

        if ( data[ dataOffset + kOffsIsMainMonitor ] != 0 )
            bIsMainMonitor = true;
        else
            bIsMainMonitor = false;
    }
from MonitorMSVM.java
After the native code returns, we're back in Java, in the MonitorHelperMSVM.getMainMonitor() method. If no error occured, we create a 'MonitorMSVM' object using the int array filled out by the native code. 'MonitorMSVM' implements the Monitor interface, and returns the information obtained, such as the Rectangle of the workarea.



Main Page · JConfig · ImageMeister · System Properties Repository · WordMeister · Free Samples · Java Freeware · Contact Us · FAQ · Links


Copyright (c) 1997-2002 Samizdat Productions. All Rights Reserved.
WarpMovie, TileMovie, JConfig, ImageMeister and MovieShredder are Trademarks of Samizdat Productions.