Wednesday, July 22, 2009

How to display a non-scrolling background for a Java JScrollPane

To add a background text (or image) to the back of a JTextArea that is inside a JScrollPane, you can use the following code. The advantage here is that the background text/image does NOT scroll with the text in the JTextArea. See screenshot below.
Here's the code:
public static void main(String[] args) {


JFrame frame = new JFrame("Overlay test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JScrollPane scroll = new JScrollPane();
scroll.getViewport().setBackground(Color.WHITE);

scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll.setPreferredSize( new Dimension(400,100));
frame.add(scroll);

final String text = "English";

final JTextArea ta = new JTextArea() {

 {setOpaque(false);}  // instance initializer

 public void paintComponent (Graphics g) {
   g.setFont(new Font("Verdana",Font.ITALIC,20));
   g.setColor(Color.LIGHT_GRAY);

   Rectangle rect = getVisibleRect();
   int x = rect.width + rect.x - 14*text.length();
   int y = rect.y + 20; // approx. height of the text
   g.drawString(text, x, y);
   super.paintComponent(g);
 }
};

ta.setText("This text area contains an overlayed text that is BEHIND this text and does not scroll");
ta.setPreferredSize( new Dimension(600,100));
scroll.setViewportView(ta);
frame.pack();
frame.setVisible(true);
}

Friday, July 17, 2009

InstallShield Setup Prerequisites for PIA 2003, PIA 2007, VSOT, .NET2.0

Now, if you are writing an "InstallShield X" package for something like an Excel Addin, you are dependent on a number of things:
  • .NET Framework (2.0, for example, dotnetfx2.0.exe)
  • Office 2007 Primary Interop Assemblies (o2007pia.msi)
  • Visual Studio Tools for Office (vstor2005.exe)
One way to do this is setting up a "Basic MSI Project" (NOTE: this doesn't work with a standard InstallShield project as pre-requisites are not supported there !!)
and add prerequisites (Tools->Prerequisite Editor) for each of these dependencies.
Now the crucial question is, which condition to set for each of these packages ?
Here's my best solution, so far (Conditions tab in Preqrequisites):
  • .NET Framework 2.0: "A File does or does not exist" [WindowsFolder]\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe --- Run setup if: Not Found
  • PIA Office 2007: "A registry key does or does not exist" HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\Windows\CurrentVersion\Uninstall\{50120000-1105-0000-0000-0000000FF1CE} --- Run setup if: Not Found
  • PIA Office 2003: "A registry key does or does not exist" HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\Windows\CurrentVersion\Uninstall\{91490409-6000-11D3-8CFE-0150048383C9} --- Run setup if: Not Found
  • Visual Studio 2005 Office Tools: "A registry key does or does not exist" HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\Windows\CurrentVersion\Uninstall\{388E4B09-3E71-4649-8921-F44A3A2954A7} --- Run setup if: Not Found
Took me a long time to figure these out, thanks Anthony ! Would be nice if this helps someone :-)

10 Seconds on Windows Assemblies

So ... Windows assemblies are these little packages a .NET application can be made of.
Kind of a way around the 'DLL hell'. Check out C:\WINDOWS\assembly to see what I mean.
Interesting to note is that the same thing looks quite different in the command shell, try:
dir C:\Windows\assembly
Details are described here:
Here's a tool to list and possibly remove assemblies (can be very handy after a bad install):

Wednesday, July 15, 2009

InstallShield and Windows Services: ServiceExistsService doesn't work

So for me, ServiceExistsService didn't work at all.
There are some permission issues apparently (see http://community.acresso.com/archive/index.php?t-169135.html)
but the solution proposed there is a tad too heavy-weight for me.
Here's an alternative, use the Registry entry of a service to figure out if the service is installed or not:
// Indicates if the service with this key (e.g. myNewService) has been installed
function BOOL windowsServiceExists(serviceKey)
string szKey,szServiceName;
number nRootKey;
begin
nRootKey = HKEY_LOCAL_MACHINE;
if (RegDBSetDefaultRoot (nRootKey) <>
MessageBox ("Unable to set HKEY_LOCAL_MACHINE.", SEVERE);
return FALSE;
endif;
szKey = "SYSTEM\\CurrentControlSet\\Services\\" + serviceKey;
//MessageBox("Testing for service: " + serviceKey, INFORMATION);
if (RegDBKeyExist (szKey) = 1 )
then
//MessageBox("found service:" + szServiceName, INFORMATION);
return TRUE;
endif;
return FALSE;
end;

How to suppress InstallShield warning W7503

If you are like me and don't like duplication you might have something like a common.rul file that contains common methods. But with the InstallShield (7.x and higher ?) compiler you get this warning if you didn't use a method:
W7503: function defined but never called
Bad thing about this is the fact that you can't easily spot real warnings from this 'warning to ignore'.
Here's how to avoid this:
1) define a dummy method where you call all your offending methods
// dummy function to supress warning 'function defined but never called'
prototype dummySuppressWarningW7503();
function dummySuppressWarningW7503()
begin
setRegistryValue("","",0,"");
end;
2) call this method someplace that is definitely executed inside an if( FALSE ):
// a little trick to stop the compiler from showing warnings
if( FALSE ) then
dummySuppressWarningW7503();
endif;
Tada ! The compiler thinks its called, but it never is.

void main()

Ok, here it goes ... instead of collecting my private Tips&Tricks, why not publish them online?
Makes it easier for me to search and maybe someone out there finds a little trick that solves his/her problem. I owe you people out there a lot of good ideas.
This blog will be about Java, Groovy, C++ (if I can't avoid it), Design Patterns, Agile Methods, possibly Berlin or, more generally, some 'Eureka' moments when things just start working again.
Enjoy !