Docking a java application to the desktop

J

josetg

Hi,

On windows, how do I make my Java application stick to one edge of the
desktop?

Say, stick to the bottom of the screen (just adjacent to the "start"
bar) and on top of all other windows.

Thanks
Jose
 
L

Liz

I too was interested so I went to your link, Andrew,
and searched for 'dock' but 'not found'
maybe your link is too hard to use ;-)
 
M

mromarkhan

Peace be unto you.

Maybe the folks over at the comp.lang.java.gui
newsgroup may have a easier, well documented,
safe, 100% java-oriented solution, but here
lives a prototype.

Screenshot
http://members.rogers.com/mromarkhan/nntp-test/AppBar.jpg



Disclaimer: Use at your own risk.

Microsoft calls it an Application Desktop Toolbar.
Using Application Desktop Toolbars
http://msdn.microsoft.com/library/d...e/shell_int/shell_int_programming/appbars.asp
I used code from a Japanese (.jp ?) website because that
is where I first encountered some workable code.
http://hp.vector.co.jp/authors/VA016117/appbar2.html
The programmer stored the code
in an .lhz archive.
The lha utility decompresses it nicely.
lhz -x filename
http://gnuwin32.sourceforge.net/packages.html
However, if you download the Platform SDK,
look in the folllowing folder structure.
C:\Program Files\Microsoft SDK\Samples\winui\Shell\AppBar\AppBar.c
It houses some well documented code about an
Application Desktop Toolbar,
and it is written in english. More
importantly, it bears resemblance to the
former code.
A programmer documented using the app bar
at this website
See Extend the Windows 95 Shell with Application Desktop Toolbars
http://www.microsoft.com/msj/archive/S274.aspx
My example, severely lacks the many options that
those sites illustrate.


Some Notes
----------
1. How to find the window handle.

The program uses the FindWindow function
HOWTO: Obtain a Console Window Handle (HWND)
http://support.microsoft.com/defaul...port/kb/articles/Q124/1/03.asp&NoWebContent=1
First it changes the title
to a timestamp, the tries to find it, then restores the original
title.

Use a canvas with a native paint method
Embedding .NET Controls in Java
http://www.codeproject.com/dotnet/javanet.asp
You must use the function
GetParent since the current handle is I guess
pointing to the heavyweight canvas.
See the comments for the following article
Embed ActiveX controls inside Java GUI
http://www.codeproject.com/java/javacom.asp

Use undocumented code
Add Mouse Wheel support to Swing Widgets
http://www.codeproject.com/java/mousewheel.asp
Using undocumented java code to access a
native window handle.

2.
The appbar should
also be the top most bar, the program uses the SetWindowPos function,
Microsoft also provides the SetWindowLong function.

3.
The appbar works properly if it is set as
a tool window.
The program uses the SetWindowLong function to make
your JFrame into a toolwindow, since documentation
contained in MSDN suggest to do so for a taskbar.
See The Taskbar
http://msdn.microsoft.com/library/d...e/shell_int/shell_int_programming/appbars.asp
"To prevent the window button from being
placed on the taskbar,
create the unowned window
with the WS_EX_TOOLWINDOW extended style."


4.
The appbar must handle events that window sents it.
The program sets a new address for the window
procedure using the SetWindowLong function.
The program stores the original procedure
because any messages that are not handled by the application
must be passed on using CallWindowProc.
See Safe Subclassing in Win32
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_subclas3.asp

5.
Since the program changes the window
style at run time, it must adhere to
the following rule.
"If you want to dynamically change a
window's style to one that doesn't
support visible taskbar buttons, you must
hide the window first (by calling ShowWindow
with SW_HIDE),
change the window style, and then show the window."
From MSDN


Usage
-----
To create an application bar, extend
MyAppBar and call method setAsBar
with the title as the first parameter
and the location as the second.
The appbar can be placed on four
different locations relative to the desktop.
The set consists of MyAppBar.LEFT, MyAppBar.RIGHT, MyAppBar.TOP,
and MyAppBar.BOTTOM.
Make sure mylib.dll is in your library path.
The program unregisters the appbar by
calling the method unSetBar.
I concerned myself with only
the Windows Me OS.
So, I did not heed to some
of the warnings in the
documentation about compatibility.


Java Code
---------

<code file="MyAppBar.java">

import javax.swing.*;
public class MyAppBar extends JFrame
{
public static final int LEFT = 1;
public static final int TOP = 2;
public static final int RIGHT = 3;
public static final int BOTTOM = 4;

public native void unSetBar();
public native void setAsBar(String title, int position);
static
{
System.loadLibrary("mylib");
}
}


</code>

<code file="MyWindow.java">

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class MyWindow extends MyAppBar
{
public MyWindow()
{
String text = "I seek Allah\'s protection from Satan the Outcast\n"+
"In the name of Allah, the Beneficent, the Merciful\n"+
"PICKTHAL: Say: O Allah! Owner of Sovereignty!\n"+
"Thou givest sovereignty unto whom Thou wilt,\n"+
"and Thou withdrawest sovereignty from whom Thou wilt.\n"+
"Thou exaltest whom Thou wilt, and Thou\n" +
"abasest whom Thou wilt. In Thy hand\n"+
"is the good. Lo! Thou art Able to do all things.\n";
this.setTitle("Java Application Desktop Toolbar");
this.setVisible(true);
this.setSize(50,50);
this.getContentPane().add(new JButton("Hello World"), BorderLayout.NORTH);
this.getContentPane().add(new JTextArea(text), BorderLayout.CENTER);
this.setAsBar(this.getTitle(), MyAppBar.LEFT);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addWindowListener(
new WindowAdapter()
{
public void windowClosing(WindowEvent en)
{
MyWindow.this.unSetBar();
}
}
);
}
public static void main(String [] args)
{
new MyWindow();
}
public void closeWindow()
{
System.exit(0);
}
}

</code>

Native Code
-----------

<code file="myfile.c">

#include "jawt_md.h"
#include <windows.h>
#include "MyAppBar.h"
#define APPBAR_CALLBACK WM_APP+1
HWND windowHandle;
WNDPROC originalWindowProcedure;
BOOL firstTime = TRUE;
UINT g_uSide;

BOOL AppBar_Register(HWND hWnd)
{
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hWnd;
abd.uCallbackMessage = APPBAR_CALLBACK;
return SHAppBarMessage(ABM_NEW, &abd);
}

BOOL AppBar_UnRegister()
{
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = windowHandle;
SHAppBarMessage(ABM_REMOVE, &abd);
return TRUE;
}

JNIEXPORT void JNICALL Java_MyAppBar_unSetBar
(JNIEnv * env, jobject obj)
{
AppBar_UnRegister();
}

void AppBar_QuerySetPos(UINT uEdge, LPSIZE lpsize, PAPPBARDATA pabd)
{
int iHeight = 0;
int iWidth = 0;

pabd->uEdge = uEdge;

pabd->rc.top = 0;
pabd->rc.bottom = GetSystemMetrics(SM_CYSCREEN);
pabd->rc.left = 0;
pabd->rc.right = GetSystemMetrics(SM_CXSCREEN);

switch(uEdge){
case ABE_LEFT:
pabd->rc.right=pabd->rc.left+lpsize->cx;
break;
case ABE_RIGHT:
pabd->rc.left=pabd->rc.right-lpsize->cx;
break;
case ABE_TOP:
pabd->rc.bottom=pabd->rc.top+lpsize->cy;
break;
case ABE_BOTTOM:
pabd->rc.top=pabd->rc.bottom-lpsize->cy;
break;
}

SHAppBarMessage(ABM_QUERYPOS, pabd);

switch (uEdge) {
case ABE_LEFT:
pabd->rc.right = pabd->rc.left + lpsize->cx;
break;

case ABE_RIGHT:
pabd->rc.left = pabd->rc.right - lpsize->cx;
break;

case ABE_TOP:
pabd->rc.bottom = pabd->rc.top + lpsize->cy;
break;

case ABE_BOTTOM:
pabd->rc.top = pabd->rc.bottom - lpsize->cy;
break;
}
SHAppBarMessage(ABM_SETPOS, pabd);
MoveWindow(pabd->hWnd, pabd->rc.left, pabd->rc.top,
pabd->rc.right - pabd->rc.left,
pabd->rc.bottom - pabd->rc.top, TRUE);
}

void AppBar_PosChanged(HWND hWnd)
{
RECT rc;
SIZE size;
APPBARDATA abd;
abd.cbSize = sizeof(abd);
abd.hWnd = hWnd;
GetWindowRect(hWnd,&rc);
size.cx=rc.right-rc.left;
size.cy=rc.bottom-rc.top;
AppBar_QuerySetPos(g_uSide, &size, &abd);
}
void AppBar_Activate(HWND hWnd)
{
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hWnd;
abd.lParam = 0;
SHAppBarMessage(ABM_ACTIVATE, &abd);
}
void AppBar_WindowPosChanged(HWND hWnd)
{
APPBARDATA abd;
abd.cbSize = sizeof(APPBARDATA);
abd.hWnd = hWnd;
abd.lParam = 0;
SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
}
void AppBar_Callback(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
switch(wParam)
{
case ABN_POSCHANGED:
AppBar_PosChanged(hWnd);
break;
}
}
int CALLBACK WndProc(HWND hWnd, UINT wMessage,WPARAM wParam, LPARAM lParam)
{
switch (wMessage)
{
case WM_ACTIVATE:
AppBar_Activate(hWnd);
break;
case WM_WINDOWPOSCHANGED:
AppBar_WindowPosChanged(hWnd);
break;
case WM_EXITSIZEMOVE:
AppBar_PosChanged(hWnd);
break;
case APPBAR_CALLBACK:
AppBar_Callback(hWnd,wParam,lParam);
break;
}
return CallWindowProc(originalWindowProcedure, hWnd, wMessage, wParam, lParam);
}

JNIEXPORT void JNICALL Java_MyAppBar_setAsBar
(JNIEnv * env, jobject obj, jstring title, jint position)
{
switch(position)
{
case 1:
g_uSide = ABE_LEFT;
break;
case 2:
g_uSide = ABE_TOP;
break;
case 3:
g_uSide = ABE_RIGHT;
break;
case 4:
g_uSide = ABE_BOTTOM;
break;
}
const char *strTitle = (*env)->GetStringUTFChars(env, title, 0);
HWND hwnd = FindWindow(NULL,strTitle);
if(hwnd == NULL)
return;
windowHandle = hwnd;
ShowWindow( windowHandle,SW_HIDE);
(*env)->ReleaseStringUTFChars(env, title, strTitle);
SetWindowLong(windowHandle,GWL_EXSTYLE,WS_EX_TOOLWINDOW );
SetWindowPos(windowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
WNDPROC wndProc = (WNDPROC) SetWindowLong(windowHandle,GWL_WNDPROC,(LONG) WndProc);
originalWindowProcedure = wndProc;
AppBar_Register(windowHandle);
AppBar_PosChanged(windowHandle);
ShowWindow( windowHandle,SW_SHOW);
}


</code>

Compilation
-----------
I use gcc, which is included with the
Mingw package.
By the way it stands for
Minimalist GNU for Windows
http://www.mingw.org/

javac MyAppBar.java
javah -jni MyAppBar
gcc -g -O2 -c -IC:/MinGW/include -Ic:/j2sdk1.4.2_04/include -Ic:/j2sdk1.4.2_04/include/win32 -g myfile.c
dllwrap -IC:/MinGW/include --output-def mylib.def --add-stdcall-alias -o mylib.dll myfile.o C:\j2sdk1.4.2_04\lib\jawt.lib -lgdi32
set path=C:\j2sdk1.4.2_04\jre\bin;.;C:\j2sdk1.4.2_04\bin;
javac MyWindow.java
java MyWindow


Have a good day.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top