Sunday, December 16, 2007

SnTT: Resolution-specific content (Windows only)

Okay, so it's not Thursday. As part of this application I'm working on I want to maximize visible content by making the UI fit to the whole screen. I'm using embedded views, which can be set to autofit both the height and width of the screen, but the height will get set to 1", which is about 3 - 5 lines. So what do you do?

I did a semi-hack to come up with something that's mostly good enough. It consists of:
  1. A two-frame frameset. The top frame has a header form, the bottom is computed to display a content form.
  2. Multiple content forms for the resolutions I know users will be using. They are named, for example, Content_1024x768 with an alias that is just the resolution.
  3. Some Win32 API code to get the current screen resolutions.
  4. Code in the header form's QueryOpen to get the current resolution.
  5. An interesting technique I learned from Kevin Pettit via SuperNTF for caching the resolution.
Here is how it fits together. The QueryOpen event of the Header form contains the following:

(Options)
Option Declare
Use "LS.BE.Win32API"

Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, Continue As Variant)
Dim session As New NotesSession
Dim db As NotesDatabase
Dim profile As NotesDocument

Dim resX As Long
Dim resY As Long

Call GetRes(resX, resY) 'LS.BE.Win32API

Set db = session.CurrentDatabase
'Here is the technique I lifted from SuperNTF
' You create a profile doc, but you don't save it
' This creates an in-memory cache but doesn't bloat the database
Set profile = db.GetProfileDocument("ServiceDatabase", Session.UserName)
Call profile.ReplaceItemValue("ScreenResolution", Cstr(resX) & "x" & Cstr(resY))

Set profile = Nothing
Set db = Nothing
Set session = Nothing
End Sub

The real magic happens in LS.BE.Win32API script library:

(Declarations)
Const HORZRES = 8
Const VERTRES = 10

Declare Function GetDesktopWindow Lib "user32" () As Long
Declare Function GetWindowDC Lib "user32" (Byval hwnd As Long) As Long
Declare Function GetDeviceCaps Lib "gdi32" (Byval hdc As Long, Byval nIndex As Long) As Long

Sub GetRes(X As Long, Y As Long)
Dim hDesktop As Long
Dim dcDesktop As Long

'Get the handle to the desktop
hDesktop = GetDesktopWindow

'Now get the device context of the desktop
dcDesktop = GetWindowDC(hDesktop)

'And finally, get the dimensions of the desktop
X = GetDeviceCaps(dcDesktop, HORZRES)
Y = GetDeviceCaps(dcDesktop, VERTRES)

End Sub

The Content form is computed as follows:



When the frameset opens the Header form's QueryOpen grabs the screen resolution, then the content frame pulls that out and uses it to calculate the form to load. What this gives me is a way to create resolution-specific content and dynamically put it into a frame. Unfortunately this is a Windows-only approach, but I'm sure something similar could be done using Java.

This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.

3 comments:

  1. Hey, Charles. I have no idea what is in your header form, but would something like this work for you?
    http://dmcnally.blogspot.com/2007/06/sntt-update-to-single-view-user.html

    Don

    ReplyDelete
  2. Darn...didn't link-enable the first one.
    SNTT

    ReplyDelete
  3. Thanks for the suggestion, Don. The problem for me is the embedded views are in a caption table, and setting the height to autofit doesn't work. That's a neat trick, though, and I'll have to play around with it. :-)

    ReplyDelete