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.