personalizar - Barra de progreso de la barra de tareas de Windows 7 en Java
personalizar progressbar java (7)
Como el java.awt.Taskbar de Java9 solo funciona para los marcos de swing antiguos (de alguna manera se olvidaron de implementar esto para javafx.stage.Stage) y com.nativelibs4java bridj no funciona (ya) (vea https://github.com/nativelibs4java/BridJ/issues/94 ) Implementé una solución utilizando JNA 4.1.0.
Tenga en cuenta:
- Se basa en llamar la ji interna de javafx (com.sun.javafx.stage.WindowHelper) - por lo que podría interrumpirse con la próxima actualización de java
- Solo establece el estado de progreso "indeterminado", pero el estado de progreso normal también debería ser posible con algunos ajustes
Espero que esto ayude.
ITaskbarList3.java
package example;
import com.sun.jna.platform.win32.Guid.IID;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HRESULT;
public interface ITaskbarList3 {
IID IID_ITASKBARLIST3 = new IID("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf"); // from ShObjIdl.h
int TBPF_NOPROGRESS = 0;
int TBPF_INDETERMINATE = 0x1;
int TBPF_NORMAL = 0x2;
int TBPF_ERROR = 0x4;
int TBPF_PAUSED = 0x8;
HRESULT SetProgressState(HWND hwnd, int tbpFlags);
}
TaskbarList3.java
package example;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.platform.win32.COM.COMInvoker;
public final class TaskbarList3 extends COMInvoker implements ITaskbarList3 {
public TaskbarList3(Pointer pointer) {
setPointer(pointer);
}
@Override
public HRESULT SetProgressState(HWND hwnd, int tbpFlags) {
return (HRESULT) this._invokeNativeObject(
10, // magic number (gathered by trial and error)
new Object[] { this.getPointer(), hwnd, tbpFlags },
HRESULT.class);
}
}
TaskbarPeer.java
package example;
import com.sun.javafx.stage.WindowHelper;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Guid.CLSID;
import com.sun.jna.platform.win32.Ole32;
import com.sun.jna.platform.win32.W32Errors;
import com.sun.jna.platform.win32.WTypes;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.ptr.PointerByReference;
import javafx.stage.Stage;
public final class TaskbarPeer {
public static void setIndeterminateProgress(Stage stage, boolean indeterminate) {
final var peer = WindowHelper.getPeer(stage);
final long windowHandle = peer.getRawHandle();
final var clsid = new CLSID("56FDF344-FD6D-11d0-958A-006097C9A090"); // from ShObjIdl.h
final var taskbarListPointerRef = new PointerByReference();
var hr = Ole32.INSTANCE.CoCreateInstance(clsid, null, WTypes.CLSCTX_SERVER,
ITaskbarList3.IID_ITASKBARLIST3, taskbarListPointerRef);
if (W32Errors.FAILED(hr)) {
throw new RuntimeException("failed with code: " + hr.intValue());
}
final TaskbarList3 taskbarList = new TaskbarList3(taskbarListPointerRef.getValue());
final var hwnd = new HWND(new Pointer(windowHandle));
final int progressState = indeterminate ? ITaskbarList3.TBPF_INDETERMINATE : ITaskbarList3.TBPF_NOPROGRESS;
hr = taskbarList.SetProgressState(hwnd, progressState);
if (W32Errors.FAILED(hr)) {
throw new RuntimeException("failed with code: " + hr.intValue());
}
}
}
Sample.java
package example;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public final class Sample extends Application {
private boolean indeterminateProgressState = false;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
final Button btn = new Button("Click me!");
primaryStage.setScene(new Scene(btn));
primaryStage.sizeToScene();
primaryStage.show();
btn.setOnAction(evt -> {
indeterminateProgressState = !indeterminateProgressState;
TaskbarPeer.setIndeterminateProgress(primaryStage, indeterminateProgressState);
});
}
}
Me gustaría saber si es posible hacer que se muestre una barra de progreso en la barra de tareas como lo hace el Explorador de Windows cuando hay una operación de archivo en curso.
Vi muchos ejemplos, pero todos implicaban C #.
SWT no lo cortará.
Descubrí que esta característica está incluida en Java 9 . Es parte de AWT y es muy simple de usar también.
Aquí hay un breve ejemplo:
import java.awt.Taskbar;
import java.awt.Taskbar.State;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
/**
* @author fxl
*/
public class TaskbarSample {
public static void main(String[] args) {
// JavaDoc:
// https://docs.oracle.com/javase/9/docs/api/java/awt/Taskbar.html
// MSDNDoc:
// https://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx
if (Taskbar.isTaskbarSupported() == false) {
return;
}
JFrame dialog = new JFrame("Test - 50%");
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
Taskbar taskbar = Taskbar.getTaskbar();
taskbar.setWindowProgressState(dialog, State.ERROR);
taskbar.setWindowProgressValue(dialog, 50);
}
}
Hay una biblioteca de Java que proporciona las nuevas características de Windows 7 para Java. Se llama J7Goodies por Strix Code . Te permite mostrar la barra de progreso de la barra de tareas y hacer mucho más.
Todavía no hay una instalación estándar en Java para hacerlo.
Por lo tanto, necesitas hablar directamente con Windows para hacerlo. Por lo tanto, debe ubicar la rutina de Windows correcta y usar JNA (probablemente la más fácil) para invocar esa rutina. No conozco un proveedor o un proyecto que ya haya hecho esto.
Editar: Parece que el proyecto http://code.google.com/p/nativelibs4java/ puede hacer lo que quieras.
Windows expone esto a través de COM. Estoy seguro de que una llamada "DLL plana" sería más fácil para usted, pero si puede acceder a COM, puede hacerlo. La interfaz COM es ITaskbarList3 (también hay una ITaskbarList4 que puede usar que hereda de ella). Http://msdn.microsoft.com/en-us/library/dd391692(VS.85).aspx lo documenta. SetProgressState y SetProgressValue son los métodos que deseará invocar. El estado es normal (verde), pausado (amarillo), error (rojo), indeterminado (swooshing verde) y ninguno. En la página de MSDN, algunas personas de la comunidad han agregado detalles de cómo llamar a este componente COM desde VB y C #, lo que podría ayudarlo a determinar la configuración y el desmontaje requerido de Java.
esto ahora es posible usando SWT, por favor revise el ejemplo del código:
org.eclipse.swt.snippets.Snippet336
This ejemplo hará el trabajo:
Código:
import org.bridj.Platform;
import org.bridj.Pointer;
import org.bridj.cpp.com.COMRuntime;
import org.bridj.cpp.com.shell.ITaskbarList3;
import org.bridj.jawt.JAWTUtils;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TaskBarListDemo extends JFrame implements ActionListener, ChangeListener
{
private ITaskbarList3 list;
private JSlider slider;
private Pointer<?> hwnd;
private TaskBarListDemo() throws ClassNotFoundException
{
super("TaskbarList Demo (" + (Platform.is64Bits() ? "64 bits" : "32 bits") + ")");
list = COMRuntime.newInstance(ITaskbarList3.class);
getContentPane().add("Center", new JLabel("Hello Native Windows 7 World !"));
Box box = Box.createVerticalBox();
int min = 0;
int max = 300;
int val = (min + max / 2);
slider = new JSlider(min, max, val);
slider.addChangeListener(this);
box.add(slider);
ButtonGroup group = new ButtonGroup();
for (ITaskbarList3.TbpFlag state : ITaskbarList3.TbpFlag.values())
{
JRadioButton cb = new JRadioButton(state.name());
group.add(cb);
cb.putClientProperty(ITaskbarList3.TbpFlag.class, state);
cb.setSelected(state == ITaskbarList3.TbpFlag.TBPF_NORMAL);
cb.addActionListener(this);
box.add(cb);
}
getContentPane().add("South", box);
}
@Override
protected void finalize() throws Throwable
{
super.finalize();
list.Release();
}
public void setVisible(boolean visible)
{
super.setVisible(visible);
long hwndVal = JAWTUtils.getNativePeerHandle(this);
hwnd = Pointer.pointerToAddress(hwndVal);
list.SetProgressValue((Pointer) hwnd, slider.getValue(), slider.getMaximum());
}
@Override
public void stateChanged(ChangeEvent actionEvent)
{
list.SetProgressValue((Pointer) hwnd, slider.getValue(), slider.getMaximum());
}
@Override
public void actionPerformed(ActionEvent actionEvent)
{
JRadioButton button = ((JRadioButton) actionEvent.getSource());
if (button.isSelected())
{
ITaskbarList3.TbpFlag flag = (ITaskbarList3.TbpFlag) button.getClientProperty(ITaskbarList3.TbpFlag.class);
list.SetProgressValue((Pointer) hwnd, slider.getValue(), slider.getMaximum());
list.SetProgressState((Pointer) hwnd, flag);
}
}
public static void main(String[] arguments) throws Exception
{
TaskBarListDemo f = new TaskBarListDemo();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
Dependencias de Maven
:
<dependencies>
<dependency>
<groupId>com.nativelibs4java</groupId>
<artifactId>bridj</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>LATEST</version>
</dependency>
</dependencies>