Goldilocks Graphics Windows

QUESTION: I am looking for a platform independent way to create a large IDL graphics window. I want it to be nearly as large as the display, but not too large. I don't want it to hide behind window decorations like title bars, nor do I want it to appear behind task bars, tool bars, start bars, and other features on my monitor. I don't want it to be too small. I want to create the graphics window in a size that is “just right.” Do you have any suggestions for me.

ANSWER: Yes. Stop being so controlling. Live a little.

If by “platform independent” you mean code that works the same on Windows, UNIX, and Macintosh computers, I have just three words for you: “In your dreams!” This is one of those platform independent issues that drive software developers crazy.

You might think the problem could be solved by asking for the graphics screen size with the Device command, like this.

   IDL> Device, Get_Screen_Size=theSize    IDL> Print, theSize
        1280    1024 

Or, alternatively, by using the IDL library function Get_Screen_Size, like this.

    IDL> theSize = Get_Screen_Size()    IDL> Print, theSize
       1280    1024 

But, you would be wrong. These commands do, in fact, return the actual size of the display or monitor, but they don't return the size of the window you need. If you make a window this size, parts of it will be either off the display or will be behind other features in the window, like the task bar or tool bar. And, note too, that on Macintosh computers, you do not get the size of your monitor returned. Rather you get the size of your monitor, minus the part of the monitor taken up by the ever-present menu bar. Here is a typical result for Macintosh computers with a 1280 by 1024 monitor.

    IDL> theSize = Get_Screen_Size()
   IDL> Print, theSize        1280    1002 

Dick Jackson has proposed a solution for Windows computers, named GetPrimaryScreenSize.

    FUNCTION GetPrimaryScreenSize, Exclude_Taskbar=exclude_Taskbar
      oMonInfo = Obj_New('IDLsysMonitorInfo')
      rects = oMonInfo -> GetRectangles(Exclude_Taskbar=exclude_Taskbar)
      pmi = oMonInfo -> GetPrimaryMonitorIndex()       Obj_Destroy, oMonInfo
      Return, rects[[2, 3], pmi]     END 

When called with the Exclude_Taskbar keyword, it will return the correct window size for Windows computers. This keyword is ignored by both UNIX and Macintosh computers.

   IDL> Print, GetPrimaryScreenSize(/EXCLUDE_TASKBAR)         1280     994 

As it happens, the IDLsysMonitorInfo method is what the IDL library routine Get_Screen_Size uses to obtain the size of the monitor, although there is no option in this routine to set the Exclude_Taskbar keyword.

Unfortunately, for UNIX computers, including the Macintosh, there is no known method to get the proper window size programmatically. However, for UNIX computers, excluding Macintosh, you can get the proper window size if you create a window the size of the monitor, then check the !D.X_Size and !D.Y_Size system variables to see what these values are actually set to. They will be set to the size you are looking for!

  ;; UNIX computers, excluding the Macintosh.   IDL> theSize = Get_Screen_Size()
  IDL> Print, theSize        1280    1024   IDL> Window, XSIZE=1280, YSIZE=1024
  IDL> Print, !D.X_Size, !D.Y_Size        1278     944 

Note that to use this solution in a program, you would have to open a window to find out what size window is required, then delete the window, then open a window of the correct size (probably after deleting the overly large window). This would cause a momentary window “flashing” as a large window was opened and deleted. An unfortunate artifact of the solution, but unavoidable.

For Macintosh computers, there is no known solution to this problem. There, you must simply resort to a “fudge factor” to estimate the size of the Macintosh dock. For many Macintosh computers, a fudge factor of 22 pixels works reasonably well.

Here is a function, named MaxWindowSize, that uses these methods to provide the maximum size of an unobscured graphics window.

Update for Mactintosh Users

Wayne Landman reports this interesting result in a Nov 3rd, 2012 IDL newsgroup post.

For the second time this week, I found a need to repeat an IDL command for it to take full effect. Below is the sample program on my Mac.

    pro testwin    print,getprimaryscreensize()
   window,xsize=870,ysize=870,retain=2    print,!D.y_size,!D.y_vsize
   print,!D.y_size,!D.y_vsize    return    end 

The output looks like this.

    IDL> testwin     
           1440         878             870         870
            856         856 

So when I first ask to print !D.y_vsize it returns 870, but when I immediately ask again it returns 856. This problem is avoided if I put any sort of wait statement after opening the window. It appears to take a finite time, after I ask IDL to open a window with a Ysize of 870 pixels, to realize that the toolbar is using up 22 pixels and adjust !Y.V_SIZE accordingly.

This delay is what may have caused the difficulty in getting the Mac useful screen size. My solution for getting the useful Mac screen size would now be the following.

    function getmacsize       xy = get_screen_size()
      window,xsize=xy[0],ysize=xy[1],/free       wait,0.01
      out = [!D.x_vsize,!D.Y_vsize]       wdelete,!D.window       return,out
   end 

Of course, this will give flashing but at least it will give the right answer.

Version of IDL used to prepare this article: IDL 8.0

Google
 
Web Coyote's Guide to IDL Programming