diff --git a/Utilities.iml b/Utilities.iml index 364bdfb..2925b37 100644 --- a/Utilities.iml +++ b/Utilities.iml @@ -10,6 +10,7 @@ + diff --git a/src/dorkbox/util/jna/windows/COLORREF.java b/src/dorkbox/util/jna/windows/COLORREF.java new file mode 100644 index 0000000..aae3454 --- /dev/null +++ b/src/dorkbox/util/jna/windows/COLORREF.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.WinNT; + +public class COLORREF extends WinNT.HANDLE { + public COLORREF() { + + } + + public COLORREF(Pointer p) { + super(p); + } +} diff --git a/src/dorkbox/util/jna/windows/GDI32.java b/src/dorkbox/util/jna/windows/GDI32.java new file mode 100644 index 0000000..d981b40 --- /dev/null +++ b/src/dorkbox/util/jna/windows/GDI32.java @@ -0,0 +1,148 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import static com.sun.jna.platform.win32.WinDef.HBITMAP; +import static com.sun.jna.platform.win32.WinDef.HDC; +import static com.sun.jna.platform.win32.WinDef.HFONT; +import static com.sun.jna.platform.win32.WinDef.RECT; +import static com.sun.jna.platform.win32.WinGDI.BITMAPINFO; +import static com.sun.jna.platform.win32.WinNT.HANDLE; + +import com.sun.jna.Native; +import com.sun.jna.NativeLibrary; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.WinUser; +import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.win32.W32APIOptions; + +import dorkbox.util.jna.windows.structs.LOGFONT; + +public +class GDI32 { + static { + Native.register(NativeLibrary.getInstance("GDI32", W32APIOptions.DEFAULT_OPTIONS)); + } + + public static final int ETO_OPAQUE = 2; + public static final int SRCCOPY = 0xCC0020; + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/dd144938(v=vs.85).aspx + */ + public static native + boolean GetTextExtentPoint32(HDC hdc, String lpString, int c, WinUser.SIZE lpSize); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/dd145093(v=vs.85).aspx + */ + public static native + COLORREF SetTextColor(HDC hdc, COLORREF crColor); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/dd162964(v=vs.85).aspx + */ + public static native + COLORREF SetBkColor(HDC hdc, COLORREF crColor); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/dd162713(v=vs.85).aspx + */ + public static native + boolean ExtTextOut(HDC hdc, int X, int Y, int fuOptions, RECT lprc, String lpString, int cbCount, int[] lpDx); + + /** + * https://msdn.microsoft.com/ru-ru/library/windows/desktop/dd183500(v=vs.85).aspx + */ + public static native + HFONT CreateFontIndirect(LOGFONT l); + + /** + * The SelectObject function selects an object into the specified device context (DC). + * The new object replaces the previous object of the same type. + * + * @param hDC Handle to the DC. + * @param hGDIObj Handle to the object to be selected. + * + * @return If the selected object is not a region and the function succeeds, the return value + * is a handle to the object being replaced. If the selected object is a region and the + * function succeeds, the return value is one of the REGION values. + */ + public static native + HANDLE SelectObject(HDC hDC, HANDLE hGDIObj); + + /** + * The CreateCompatibleDC function creates a memory device context (DC) compatible with the specified device. + * + * @param hDC Handle to an existing DC. If this handle is NULL, the function creates a memory DC compatible with the + * application's current screen. + * + * @return If the function succeeds, the return value is the handle to a memory DC. + * If the function fails, the return value is NULL. + * To get extended error information, call GetLastError. + */ + public static native + HDC CreateCompatibleDC(HDC hDC); + + /** + * The DeleteDC function deletes the specified device context (DC). + * + * @param hDC Handle to the device context. + * + * @return If the function succeeds, the return value is nonzero. + * If the function fails, the return value is zero. + * To get extended error information, call GetLastError. + */ + public static native + boolean DeleteDC(HDC hDC); + + /** + * The DeleteObject function deletes a logical pen, brush, font, bitmap, region, or palette, + * freeing all system resources associated with the object. After the object is deleted, the + * specified handle is no longer valid. + * + * @param hObject Handle to a logical pen, brush, font, bitmap, region, or palette. + * + * @return If the function succeeds, the return value is nonzero. + * If the specified handle is not valid or is currently selected into a DC, the return value is zero. + * To get extended error information, call GetLastError. + */ + public static native + boolean DeleteObject(HANDLE hObject); + + /** + * The CreateDIBSection function creates a DIB that applications can write to directly. + * The function gives you a pointer to the location of the bitmap bit values. You can supply + * a handle to a file-mapping object that the function will use to create the bitmap, or you + * can let the system allocate the memory for the bitmap. + * + * @param hDC Handle to a device context. If the value of iUsage is DIB_PAL_COLORS, the function uses this + * device context's logical palette to initialize the DIB colors. + * @param pbmi Pointer to a BITMAPINFO structure that specifies various attributes of the DIB, including + * the bitmap dimensions and colors. + * @param iUsage Specifies the type of data contained in the bmiColors array member of the BITMAPINFO structure + * pointed to by pbmi (either logical palette indexes or literal RGB values). + * @param ppvBits Pointer to a variable that receives a pointer to the location of the DIB bit values. + * @param hSection Handle to a file-mapping object that the function will use to create the DIB. This parameter can be NULL. + * @param dwOffset Specifies the offset from the beginning of the file-mapping object referenced by hSection where storage + * for the bitmap bit values is to begin. + * + * @return Specifies the offset from the beginning of the file-mapping object referenced by hSection where storage + * for the bitmap bit values is to begin. + */ + public static native + HBITMAP CreateDIBSection(HDC hDC, BITMAPINFO pbmi, int iUsage, PointerByReference ppvBits, Pointer hSection, int dwOffset); +} diff --git a/src/dorkbox/util/jna/windows/Gdi32.java b/src/dorkbox/util/jna/windows/Gdi32.java index f5a945a..46c6e9d 100644 --- a/src/dorkbox/util/jna/windows/Gdi32.java +++ b/src/dorkbox/util/jna/windows/Gdi32.java @@ -15,7 +15,7 @@ */ package dorkbox.util.jna.windows; -import com.sun.jna.Pointer; +import static com.sun.jna.platform.win32.WinDef.HDC; import dorkbox.util.jna.JnaHelper; @@ -46,5 +46,5 @@ class Gdi32 { * @param handle A handle to the DC. * @param nIndex The item to be returned. */ - public static native int GetDeviceCaps(Pointer handle, int nIndex); + public static native int GetDeviceCaps(HDC handle, int nIndex); } diff --git a/src/dorkbox/util/jna/windows/GetLastErrorException.java b/src/dorkbox/util/jna/windows/GetLastErrorException.java new file mode 100644 index 0000000..a5af535 --- /dev/null +++ b/src/dorkbox/util/jna/windows/GetLastErrorException.java @@ -0,0 +1,33 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +public +class GetLastErrorException extends RuntimeException { + private static final long serialVersionUID = 3980497906900380359L; + + private String message; + + public + GetLastErrorException() { + message = Kernel32.getLastErrorMessage(); + } + + public + String toString() { + return message; + } +} diff --git a/src/dorkbox/util/jna/windows/HBITMAPWrap.java b/src/dorkbox/util/jna/windows/HBITMAPWrap.java new file mode 100644 index 0000000..d643e7c --- /dev/null +++ b/src/dorkbox/util/jna/windows/HBITMAPWrap.java @@ -0,0 +1,104 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import static com.sun.jna.platform.win32.WinDef.HBITMAP; +import static com.sun.jna.platform.win32.WinDef.HDC; + +import java.awt.AlphaComposite; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.awt.image.Raster; + +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.WinGDI; +import com.sun.jna.ptr.PointerByReference; + +public class HBITMAPWrap extends HBITMAP { + + // https://github.com/twall/jna/blob/master/contrib/alphamaskdemo/com/sun/jna/contrib/demo/AlphaMaskDemo.java + private static + HBITMAP createBitmap(BufferedImage image) { + int w = image.getWidth(null); + int h = image.getHeight(null); + HDC screenDC = User32.IMPL.GetDC(null); + HDC memDC = GDI32.CreateCompatibleDC(screenDC); + HBITMAP hBitmap = null; + + try { + BufferedImage buf = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); + Graphics2D g = (Graphics2D) buf.getGraphics(); + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); + g.drawImage(image, 0, 0, w, h, null); + + WinGDI.BITMAPINFO bmi = new WinGDI.BITMAPINFO(); + bmi.bmiHeader.biWidth = w; + bmi.bmiHeader.biHeight = h; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = WinGDI.BI_RGB; + bmi.bmiHeader.biSizeImage = w * h * 4; + + PointerByReference ppbits = new PointerByReference(); + hBitmap = GDI32.CreateDIBSection(memDC, bmi, WinGDI.DIB_RGB_COLORS, ppbits, null, 0); + Pointer pbits = ppbits.getValue(); + + Raster raster = buf.getData(); + int[] pixel = new int[4]; + int[] bits = new int[w * h]; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + raster.getPixel(x, h - y - 1, pixel); + int red = (pixel[2] & 0xFF) << 0; + int green = (pixel[1] & 0xFF) << 8; + int blue = (pixel[0] & 0xFF) << 16; + int alpha = (pixel[3] & 0xFF) << 24; + bits[x + y * w] = alpha | red | green | blue; + } + } + pbits.write(0, bits, 0, bits.length); + return hBitmap; + } finally { + User32.IMPL.ReleaseDC(null, screenDC); + GDI32.DeleteDC(memDC); + } + } + + BufferedImage img; + + public HBITMAPWrap(BufferedImage img) { + setPointer(createBitmap(img).getPointer()); + + this.img = img; + } + + @Override + protected void finalize() throws Throwable { + close(); + super.finalize(); + } + + public void close() { + if (Pointer.nativeValue(getPointer()) != 0) { + GDI32.DeleteObject(this); + setPointer(new Pointer(0)); + } + } + + public BufferedImage getImage() { + return img; + } +} diff --git a/src/dorkbox/util/jna/windows/HICONWrap.java b/src/dorkbox/util/jna/windows/HICONWrap.java new file mode 100644 index 0000000..8e777d4 --- /dev/null +++ b/src/dorkbox/util/jna/windows/HICONWrap.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import static com.sun.jna.platform.win32.WinDef.HBITMAP; +import static com.sun.jna.platform.win32.WinDef.HICON; + +import com.sun.jna.Pointer; + +import dorkbox.util.jna.windows.structs.ICONINFO; + +/** + * http://www.pinvoke.net/default.aspx/user32.createiconindirect + */ +public class HICONWrap extends HICON { + + static HICON createIconIndirect(HBITMAP bm) { + ICONINFO info = new ICONINFO(); + info.IsIcon = true; + info.MaskBitmap = bm; + info.ColorBitmap = bm; + + HICON hicon = User32.IMPL.CreateIconIndirect(info); + if (hicon == null) { + throw new GetLastErrorException(); + } + + return hicon; + } + + private HBITMAPWrap bm; + + public HICONWrap() { + } + + public HICONWrap(Pointer p) { + super(p); + } + + public HICONWrap(HBITMAPWrap bm) { + this.bm = bm; + setPointer(createIconIndirect(bm).getPointer()); + } + + public void close() { + bm.close(); + + if (Pointer.nativeValue(getPointer()) != 0) { + GDI32.DeleteObject(this); + setPointer(new Pointer(0)); + } + } + + @Override + protected void finalize() throws Throwable { + close(); + super.finalize(); + } +} diff --git a/src/dorkbox/util/jna/windows/Kernel32.java b/src/dorkbox/util/jna/windows/Kernel32.java new file mode 100644 index 0000000..3971c07 --- /dev/null +++ b/src/dorkbox/util/jna/windows/Kernel32.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import com.sun.jna.Memory; +import com.sun.jna.ptr.PointerByReference; + +public +class Kernel32 { + public static + String getLastErrorMessage() { + // has to be Kernel32.INSTANCE, otherwise it will crash the JVM + int hresult = com.sun.jna.platform.win32.Kernel32.INSTANCE.GetLastError(); + if (hresult == 0) { + return "HRESULT: 0x0 [No Error]"; + } else { + Memory memory = new Memory(1024); + PointerByReference reference = new PointerByReference(memory); + + // Must be Kernel32.INSTANCE because of how it pulls in variety arguments. + com.sun.jna.platform.win32.Kernel32.INSTANCE.FormatMessage(com.sun.jna.platform.win32.Kernel32.FORMAT_MESSAGE_FROM_SYSTEM, null, hresult, 0, reference, (int) memory.size(), null); + + String memoryMessage = reference.getPointer() + .getString(0, true); + memoryMessage = memoryMessage.trim(); + + return String.format("HRESULT: 0x%08x [%s]", hresult, memoryMessage); + } + } +} diff --git a/src/dorkbox/util/jna/windows/Listener.java b/src/dorkbox/util/jna/windows/Listener.java new file mode 100644 index 0000000..4b51710 --- /dev/null +++ b/src/dorkbox/util/jna/windows/Listener.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import static com.sun.jna.platform.win32.WinDef.HWND; +import static com.sun.jna.platform.win32.WinDef.LPARAM; +import static com.sun.jna.platform.win32.WinDef.WPARAM; + +public +class Listener { + public + void run(HWND hWnd, WPARAM wParam, LPARAM lParam) { + + } +} diff --git a/src/dorkbox/util/jna/windows/MSG.java b/src/dorkbox/util/jna/windows/MSG.java new file mode 100644 index 0000000..77c0fd1 --- /dev/null +++ b/src/dorkbox/util/jna/windows/MSG.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; + +public +class MSG extends Structure { + public Pointer hWnd; + public int message; + public Parameter wParam; + public Parameter lParam; + public int time; + public int x; + public int y; + + @Override + protected + List getFieldOrder() { + return Arrays.asList("hWnd", "message", "wParam", "lParam", "time", "x", "y"); + } +} diff --git a/src/dorkbox/util/jna/windows/MsImg32.java b/src/dorkbox/util/jna/windows/MsImg32.java new file mode 100644 index 0000000..142f6bb --- /dev/null +++ b/src/dorkbox/util/jna/windows/MsImg32.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import com.sun.jna.Native; +import com.sun.jna.NativeLibrary; +import com.sun.jna.platform.win32.WinDef; +import com.sun.jna.win32.W32APIOptions; + +import dorkbox.util.jna.windows.structs.BLENDFUNCTION; + +public +class MsImg32 { + static { + Native.register(NativeLibrary.getInstance("Msimg32", W32APIOptions.DEFAULT_OPTIONS)); + } + + public static final int ETO_OPAQUE = 2; + public static final int SRCCOPY = 0xCC0020; + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/dd183351(v=vs.85).aspx + */ + public static native + boolean AlphaBlend(WinDef.HDC hdcDest, int xoriginDest, int yoriginDest, int wDest, int hDest, WinDef.HDC hdcSrc, int xoriginSrc, + int yoriginSrc, int wSrc, int hSrc, BLENDFUNCTION.ByValue ftn); +} diff --git a/src/dorkbox/util/jna/windows/Parameter.java b/src/dorkbox/util/jna/windows/Parameter.java new file mode 100644 index 0000000..7121d5e --- /dev/null +++ b/src/dorkbox/util/jna/windows/Parameter.java @@ -0,0 +1,17 @@ +package dorkbox.util.jna.windows; + +import com.sun.jna.IntegerType; +import com.sun.jna.Pointer; + +public +class Parameter extends IntegerType { + public + Parameter() { + this(0); + } + + public + Parameter(long value) { + super(Pointer.SIZE, value); + } +} diff --git a/src/dorkbox/util/jna/windows/ShCore.java b/src/dorkbox/util/jna/windows/ShCore.java index 80e9aae..ddc307f 100644 --- a/src/dorkbox/util/jna/windows/ShCore.java +++ b/src/dorkbox/util/jna/windows/ShCore.java @@ -65,4 +65,7 @@ class ShCore { */ public static native Pointer GetDpiForMonitor(Pointer hmonitor, int dpiType, IntByReference dpiX, IntByReference dpiY); + + public static native + Pointer SetProcessDpiAwareness(int dpiAwareness); } diff --git a/src/dorkbox/util/jna/windows/Shell32.java b/src/dorkbox/util/jna/windows/Shell32.java new file mode 100644 index 0000000..33086ae --- /dev/null +++ b/src/dorkbox/util/jna/windows/Shell32.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import com.sun.jna.Native; +import com.sun.jna.NativeLibrary; +import com.sun.jna.win32.W32APIOptions; + +import dorkbox.util.jna.windows.structs.NOTIFYICONDATA; + +public +class Shell32 { + static { + Native.register(NativeLibrary.getInstance("shell32", W32APIOptions.DEFAULT_OPTIONS)); + } + + static public final int NIM_ADD = 0x0; + static public final int NIM_MODIFY = 0x1; + static public final int NIM_DELETE = 0x2; + + public static native + boolean Shell_NotifyIcon(int dwMessage, NOTIFYICONDATA lpdata); +} diff --git a/src/dorkbox/util/jna/windows/User32.java b/src/dorkbox/util/jna/windows/User32.java index 48aa0fd..a819a5f 100644 --- a/src/dorkbox/util/jna/windows/User32.java +++ b/src/dorkbox/util/jna/windows/User32.java @@ -15,45 +15,233 @@ */ package dorkbox.util.jna.windows; +import static com.sun.jna.platform.win32.WinDef.HDC; +import static com.sun.jna.platform.win32.WinDef.HICON; +import static com.sun.jna.platform.win32.WinDef.HINSTANCE; +import static com.sun.jna.platform.win32.WinDef.HMENU; +import static com.sun.jna.platform.win32.WinDef.HWND; +import static com.sun.jna.platform.win32.WinDef.LPARAM; +import static com.sun.jna.platform.win32.WinDef.LRESULT; +import static com.sun.jna.platform.win32.WinDef.POINT; +import static com.sun.jna.platform.win32.WinDef.RECT; +import static com.sun.jna.platform.win32.WinDef.WPARAM; + +import com.sun.jna.Callback; import com.sun.jna.Pointer; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.WinNT; -import dorkbox.util.jna.JnaHelper; +import dorkbox.util.OS; +import dorkbox.util.jna.windows.structs.ICONINFO; +import dorkbox.util.jna.windows.structs.MENUITEMINFO; +import dorkbox.util.jna.windows.structs.NONCLIENTMETRICS; - -/** - * bindings for User32 - *

- * Direct-mapping, See: https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md - */ +@SuppressWarnings("WeakerAccess") public -class User32 { +interface User32 { + User32 IMPL = OS.is64bit() ? new User32_64() : new User32_32(); - static { - JnaHelper.register("user32", User32.class); - } + int SPI_GETNONCLIENTMETRICS = 0x0029; + int COLOR_MENU = 4; + int COLOR_MENUTEXT = 7; + int COLOR_HIGHLIGHTTEXT = 14; + int COLOR_HIGHLIGHT = 13; + int COLOR_GRAYTEXT = 17; + + int GWL_WNDPROC = -4; + + int WM_LBUTTONUP = 0x202; + int WM_RBUTTONUP = 0x205; + + int MF_BYPOSITION = 0x400; + + /** + * This is overridden by the 64-bit version to be SetWindowLongPtr instead. + */ + int SetWindowLong(HWND hWnd, int nIndex, Callback procedure); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms647626(v=vs.85).aspx + */ + HMENU CreatePopupMenu(); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms647616(v=vs.85).aspx + */ + boolean AppendMenu(HMENU hMenu, int uFlags, int uIDNewItem, String lpNewItem); + + /** + * https://msdn.microsoft.com/en-us/library/windows/desktop/ms647629(v=vs.85).aspx + */ + boolean DeleteMenu(HMENU hMenu, int uPosition, int uFlags); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms647631(v=vs.85).aspx + */ + boolean DestroyMenu(HMENU hMenu); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms648002(v=vs.85).aspx + */ + boolean TrackPopupMenu(HMENU hMenu, int uFlags, int x, int y, int nReserved, HWND hWnd, RECT prcRect); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms648001(v=vs.85).aspx + */ + boolean SetMenuItemInfo(HMENU hMenu, int uItem, boolean fByPosition, MENUITEMINFO lpmii); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms647980(v=vs.85).aspx + */ + boolean GetMenuItemInfo(HMENU hMenu, int uItem, boolean fByPosition, MENUITEMINFO lpmii); + + /** + * Brings the thread that created the specified window into the foreground + * and activates the window. Keyboard input is directed to the window, and + * various visual cues are changed for the user. The system assigns a + * slightly higher priority to the thread that created the foreground window + * than it does to other threads. + * + * @param hWnd A handle to the window that should be activated and brought to + * the foreground. + * + * @return If the window was brought to the foreground, the return value is + * nonzero. + */ + boolean SetForegroundWindow(HWND hWnd); + + /** + * The GetSystemMetrics function retrieves various system metrics (widths + * and heights of display elements) and system configuration settings. All + * dimensions retrieved by GetSystemMetrics are in pixels. + * + * @param nIndex System metric or configuration setting to retrieve. This + * parameter can be one of the following values. Note that all + * SM_CX* values are widths and all SM_CY* values are heights. + * Also note that all settings designed to return Boolean data + * represent TRUE as any nonzero value, and FALSE as a zero + * value. + * + * @return If the function succeeds, the return value is the requested + * system metric or configuration setting. If the function fails, + * the return value is zero. GetLastError does not provide extended + * error information. + */ + int GetSystemMetrics(int nIndex); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms633500(v=vs.85).aspx + */ + HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter, String lpszClass, String lpszWindow); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx + */ + LRESULT SendMessage(HWND hWnd, int Msg, WPARAM wParam, LPARAM lParam); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms648062(v=vs.85).aspx + */ + HICON CreateIconIndirect(ICONINFO piconinfo); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms632682(v=vs.85).aspx + */ + boolean DestroyWindow(HWND hWnd); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724947(v=vs.85).aspx + */ + boolean SystemParametersInfo(int uiAction, int uiParam, NONCLIENTMETRICS pvParam, int fWinIni); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms724371(v=vs.85).aspx + */ + COLORREF GetSysColor(int nIndex); + + /** + * This function places a message in the message queue associated with the + * thread that created the specified window and then returns without waiting + * for the thread to process the message. Messages in a message queue are + * retrieved by calls to the GetMessage or PeekMessage function. + * + * @param hWnd Handle to the window whose window procedure is to receive the + * message. + * @param msg Specifies the message to be posted. + * @param wParam Specifies additional message-specific information. + * @param lParam Specifies additional message-specific information. + */ + void PostMessage(HWND hWnd, int msg, WPARAM wParam, LPARAM lParam); + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms632680(v=vs.85).aspx + */ + HWND CreateWindowEx(int dwExStyle, + String lpClassName, + String lpWindowName, + int dwStyle, + int x, + int y, + int nWidth, + int nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + WinNT.HANDLE lpParam); + + + /** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms644947(v=vs.85).aspx + */ + LRESULT DefWindowProc(HWND hWnd, int Msg, WPARAM wParam, LPARAM lParam); + + boolean GetMessage(MSG lpMsg, Pointer hWnd, int wMsgFilterMin, int wMsgFilterMax); + + boolean TranslateMessage(MSG lpMsg); + + boolean DispatchMessage(MSG lpMsg); + + int RegisterWindowMessage(WString lpString); /** * https://msdn.microsoft.com/en-us/library/windows/desktop/dd144871(v=vs.85).aspx * - * @param shouldBeNull A handle to the window whose DC is to be retrieved. If this value is NULL, GetDC retrieves the DC for the entire - * screen. + * This function retrieves a handle to a display device context (DC) for the + * client area of the specified window. The display device context can be + * used in subsequent graphics display interface (GDI) functions to draw in + * the client area of the window. * - * @return if the function succeeds, the return value is a handle to the DC for the specified window's client area. If the function - * fails, the return value is NULL. + * @param hWnd Handle to the window whose device context is to be retrieved. + * If this value is NULL, GetDC retrieves the device context for + * the entire screen. + * + * @return The handle the device context for the specified window's client + * area indicates success. NULL indicates failure. To get extended + * error information, call GetLastError. */ - public static native - Pointer GetDC(Pointer shouldBeNull); + HDC GetDC(HWND hWnd); /** * https://msdn.microsoft.com/en-us/library/windows/desktop/dd162920(v=vs.85).aspx + * + * This function releases a device context (DC), freeing it for use by other + * applications. The effect of ReleaseDC depends on the type of device + * context. + * + * @param hWnd Handle to the window whose device context is to be released. + * @param hDC Handle to the device context to be released. + * + * @return The return value specifies whether the device context is + * released. 1 indicates that the device context is released. Zero + * indicates that the device context is not released. */ - public static native - void ReleaseDC(Pointer shouldBeNull, Pointer dcHandle); + int ReleaseDC(HWND hWnd, HDC hDC); + boolean GetCursorPos(POINT point); + /** * https://msdn.microsoft.com/en-us/library/windows/desktop/dd145062(v=vs.85).aspx */ - public static native - Pointer MonitorFromPoint(POINT.ByValue pt, int shouldBeOne); + Pointer MonitorFromPoint(POINT pt, int shouldBeOne); } diff --git a/src/dorkbox/util/jna/windows/User32_32.java b/src/dorkbox/util/jna/windows/User32_32.java new file mode 100644 index 0000000..fe6d237 --- /dev/null +++ b/src/dorkbox/util/jna/windows/User32_32.java @@ -0,0 +1,179 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import static com.sun.jna.platform.win32.WinDef.HDC; +import static com.sun.jna.platform.win32.WinDef.HICON; +import static com.sun.jna.platform.win32.WinDef.HINSTANCE; +import static com.sun.jna.platform.win32.WinDef.HMENU; +import static com.sun.jna.platform.win32.WinDef.HWND; +import static com.sun.jna.platform.win32.WinDef.LPARAM; +import static com.sun.jna.platform.win32.WinDef.LRESULT; +import static com.sun.jna.platform.win32.WinDef.POINT; +import static com.sun.jna.platform.win32.WinDef.RECT; +import static com.sun.jna.platform.win32.WinDef.WPARAM; + +import com.sun.jna.Callback; +import com.sun.jna.Native; +import com.sun.jna.NativeLibrary; +import com.sun.jna.Pointer; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.win32.W32APIOptions; + +import dorkbox.util.jna.windows.structs.ICONINFO; +import dorkbox.util.jna.windows.structs.MENUITEMINFO; +import dorkbox.util.jna.windows.structs.NONCLIENTMETRICS; + +/** + * On first glance, this appears to be unnecessary to have a DirectMapping class implement an interface - however this is so different + * methods can be overridden by the correct 64bit versions, otherwise multiple copies of this library would have to be loaded (one for + * "normal", and another for the "special case"). + * + * Doing it this way greatly simplifies the API while maintaining Direct Mapping, at the cost of a slightly more complex code hierarchy. + */ +public +class User32_32 implements User32 { + static { + Native.register(NativeLibrary.getInstance("user32", W32APIOptions.DEFAULT_OPTIONS)); + } + + // is replaced by the 64bit version + @Override + public native + int SetWindowLong(HWND hWnd, int nIndex, Callback procedure); + + @Override + public native + HMENU CreatePopupMenu(); + + @Override + public native + boolean AppendMenu(final HMENU hMenu, final int uFlags, final int uIDNewItem, final String lpNewItem); + + @Override + public native + boolean DeleteMenu(final HMENU hMenu, final int uPosition, final int uFlags); + + @Override + public native + boolean DestroyMenu(final HMENU hMenu); + + @Override + public native + boolean TrackPopupMenu(final HMENU hMenu, + final int uFlags, + final int x, + final int y, + final int nReserved, + final HWND hWnd, + final RECT prcRect); + + @Override + public native + boolean SetMenuItemInfo(final HMENU hMenu, final int uItem, final boolean fByPosition, final MENUITEMINFO lpmii); + + @Override + public native + boolean GetMenuItemInfo(final HMENU hMenu, final int uItem, final boolean fByPosition, final MENUITEMINFO lpmii); + + @Override + public native + boolean SetForegroundWindow(final HWND hWnd); + + @Override + public native + int GetSystemMetrics(final int nIndex); + + @Override + public native + HWND FindWindowEx(final HWND hwndParent, final HWND hwndChildAfter, final String lpszClass, final String lpszWindow); + + @Override + public native + LRESULT SendMessage(final HWND hWnd, final int Msg, final WPARAM wParam, final LPARAM lParam); + + @Override + public native + HICON CreateIconIndirect(final ICONINFO piconinfo); + + @Override + public native + boolean DestroyWindow(final HWND hWnd); + + @Override + public native + boolean SystemParametersInfo(final int uiAction, final int uiParam, final NONCLIENTMETRICS pvParam, final int fWinIni); + + @Override + public native + COLORREF GetSysColor(final int nIndex); + + @Override + public native + void PostMessage(final HWND hWnd, final int msg, final WPARAM wParam, final LPARAM lParam); + + @Override + public native + HWND CreateWindowEx(final int dwExStyle, + final String lpClassName, + final String lpWindowName, + final int dwStyle, + final int x, + final int y, + final int nWidth, + final int nHeight, + final HWND hWndParent, + final HMENU hMenu, + final HINSTANCE hInstance, + final WinNT.HANDLE lpParam); + + @Override + public native + LRESULT DefWindowProc(final HWND hWnd, final int Msg, final WPARAM wParam, final LPARAM lParam); + + @Override + public native + boolean GetMessage(final MSG lpMsg, final Pointer hWnd, final int wMsgFilterMin, final int wMsgFilterMax); + + @Override + public native + boolean TranslateMessage(final MSG lpMsg); + + @Override + public native + boolean DispatchMessage(final MSG lpMsg); + + @Override + public native + int RegisterWindowMessage(final WString lpString); + + @Override + public native + HDC GetDC(final HWND hWnd); + + @Override + public native + int ReleaseDC(final HWND hWnd, final HDC hDC); + + @Override + public native + boolean GetCursorPos(final POINT point); + + @Override + public native + Pointer MonitorFromPoint(final POINT pt, final int shouldBeOne); +} diff --git a/src/dorkbox/util/jna/windows/User32_64.java b/src/dorkbox/util/jna/windows/User32_64.java new file mode 100644 index 0000000..060b490 --- /dev/null +++ b/src/dorkbox/util/jna/windows/User32_64.java @@ -0,0 +1,184 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import static com.sun.jna.platform.win32.WinDef.HDC; +import static com.sun.jna.platform.win32.WinDef.HICON; +import static com.sun.jna.platform.win32.WinDef.HINSTANCE; +import static com.sun.jna.platform.win32.WinDef.HMENU; +import static com.sun.jna.platform.win32.WinDef.HWND; +import static com.sun.jna.platform.win32.WinDef.LPARAM; +import static com.sun.jna.platform.win32.WinDef.LRESULT; +import static com.sun.jna.platform.win32.WinDef.POINT; +import static com.sun.jna.platform.win32.WinDef.RECT; +import static com.sun.jna.platform.win32.WinDef.WPARAM; + +import com.sun.jna.Callback; +import com.sun.jna.Native; +import com.sun.jna.NativeLibrary; +import com.sun.jna.Pointer; +import com.sun.jna.WString; +import com.sun.jna.platform.win32.WinNT; +import com.sun.jna.win32.W32APIOptions; + +import dorkbox.util.jna.windows.structs.ICONINFO; +import dorkbox.util.jna.windows.structs.MENUITEMINFO; +import dorkbox.util.jna.windows.structs.NONCLIENTMETRICS; + +/** + * On first glance, this appears to be unnecessary to have a DirectMapping class implement an interface - however this is so different + * methods can be overridden by the correct 64bit versions, otherwise multiple copies of this library would have to be loaded (one for + * "normal", and another for the "special case"). + * + * Doing it this way greatly simplifies the API while maintaining Direct Mapping, at the cost of a slightly more complex code hierarchy. + */ +public +class User32_64 implements User32 { + static { + Native.register(NativeLibrary.getInstance("user32", W32APIOptions.DEFAULT_OPTIONS)); + } + + @Override + public + int SetWindowLong(HWND hWnd, int nIndex, Callback procedure) { + return SetWindowLongPtr(hWnd, nIndex, procedure); + } + + // should be used instead of SetWindowLong for 64 versions + public native + int SetWindowLongPtr(HWND hWnd, int nIndex, Callback procedure); + + @Override + public native + HMENU CreatePopupMenu(); + + @Override + public native + boolean AppendMenu(final HMENU hMenu, final int uFlags, final int uIDNewItem, final String lpNewItem); + + @Override + public native + boolean DeleteMenu(final HMENU hMenu, final int uPosition, final int uFlags); + + @Override + public native + boolean DestroyMenu(final HMENU hMenu); + + @Override + public native + boolean TrackPopupMenu(final HMENU hMenu, + final int uFlags, + final int x, + final int y, + final int nReserved, + final HWND hWnd, + final RECT prcRect); + + @Override + public native + boolean SetMenuItemInfo(final HMENU hMenu, final int uItem, final boolean fByPosition, final MENUITEMINFO lpmii); + + @Override + public native + boolean GetMenuItemInfo(final HMENU hMenu, final int uItem, final boolean fByPosition, final MENUITEMINFO lpmii); + + @Override + public native + boolean SetForegroundWindow(final HWND hWnd); + + @Override + public native + int GetSystemMetrics(final int nIndex); + + @Override + public native + HWND FindWindowEx(final HWND hwndParent, final HWND hwndChildAfter, final String lpszClass, final String lpszWindow); + + @Override + public native + LRESULT SendMessage(final HWND hWnd, final int Msg, final WPARAM wParam, final LPARAM lParam); + + @Override + public native + HICON CreateIconIndirect(final ICONINFO piconinfo); + + @Override + public native + boolean DestroyWindow(final HWND hWnd); + + @Override + public native + boolean SystemParametersInfo(final int uiAction, final int uiParam, final NONCLIENTMETRICS pvParam, final int fWinIni); + + @Override + public native + COLORREF GetSysColor(final int nIndex); + + @Override + public native + void PostMessage(final HWND hWnd, final int msg, final WPARAM wParam, final LPARAM lParam); + + @Override + public native + HWND CreateWindowEx(final int dwExStyle, + final String lpClassName, + final String lpWindowName, + final int dwStyle, + final int x, + final int y, + final int nWidth, + final int nHeight, + final HWND hWndParent, + final HMENU hMenu, + final HINSTANCE hInstance, + final WinNT.HANDLE lpParam); + + @Override + public native + LRESULT DefWindowProc(final HWND hWnd, final int Msg, final WPARAM wParam, final LPARAM lParam); + + @Override + public native + boolean GetMessage(final MSG lpMsg, final Pointer hWnd, final int wMsgFilterMin, final int wMsgFilterMax); + + @Override + public native + boolean TranslateMessage(final MSG lpMsg); + + @Override + public native + boolean DispatchMessage(final MSG lpMsg); + + @Override + public native + int RegisterWindowMessage(final WString lpString); + + @Override + public native + HDC GetDC(final HWND hWnd); + + @Override + public native + int ReleaseDC(final HWND hWnd, final HDC hDC); + + @Override + public native + boolean GetCursorPos(final POINT point); + + @Override + public native + Pointer MonitorFromPoint(final POINT pt, final int shouldBeOne); +} diff --git a/src/dorkbox/util/jna/windows/WNDPROC.java b/src/dorkbox/util/jna/windows/WNDPROC.java new file mode 100644 index 0000000..05517bc --- /dev/null +++ b/src/dorkbox/util/jna/windows/WNDPROC.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import static com.sun.jna.platform.win32.WinDef.HWND; +import static com.sun.jna.platform.win32.WinDef.LPARAM; +import static com.sun.jna.platform.win32.WinDef.LRESULT; +import static com.sun.jna.platform.win32.WinDef.WPARAM; + +import com.sun.jna.win32.StdCallLibrary; + +public +interface WNDPROC extends StdCallLibrary.StdCallCallback { + LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam); +} diff --git a/src/dorkbox/util/jna/windows/WindowsEventDispatch.java b/src/dorkbox/util/jna/windows/WindowsEventDispatch.java new file mode 100644 index 0000000..fd2ec60 --- /dev/null +++ b/src/dorkbox/util/jna/windows/WindowsEventDispatch.java @@ -0,0 +1,209 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows; + +import static com.sun.jna.platform.win32.WinDef.HWND; +import static com.sun.jna.platform.win32.WinDef.LPARAM; +import static com.sun.jna.platform.win32.WinDef.LRESULT; +import static com.sun.jna.platform.win32.WinDef.WPARAM; +import static com.sun.jna.platform.win32.WinUser.WM_QUIT; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.sun.jna.WString; +import com.sun.jna.platform.win32.WinUser; + +@SuppressWarnings({"Convert2Lambda", "UnusedAssignment", "Convert2Diamond", "FieldCanBeLocal"}) +public +class WindowsEventDispatch implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(WindowsEventDispatch.class); + + private static final String NAME = "WindowsEventDispatch"; + + public static final int WM_TASKBARCREATED = User32.IMPL.RegisterWindowMessage(new WString("TaskbarCreated")); + public static final int WM_COMMAND = 0x0111; + public static final int WM_SHELLNOTIFY = WinUser.WM_USER + 1; + public static final int WM_MEASUREITEM = 44; + public static final int WM_DRAWITEM = 43; + + public static final int MF_POPUP = 0x00000010; + + + private static final WindowsEventDispatch edt = new WindowsEventDispatch(); + private final static Map> messageIDs = new HashMap>(); + + private static final Object lock = new Object(); + private static int referenceCount = 0; + + + private Thread dispatchThread; + + // keep these around to prevent GC + private WNDPROC WndProc; + + // used to dispatch messages + private volatile HWND hWnd; + + + private + WindowsEventDispatch() { + } + + public static + void start() { + synchronized (lock) { + int ref = referenceCount++; + + if (ref == 0) { + edt.start_(); + } + + try { + // wait for the dispatch thread to start + lock.wait(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + public static + void stop() { + synchronized (lock) { + if (--referenceCount == 0) { + edt.stop_(); + } + } + } + + public static + HWND get() { + return edt.hWnd; + } + + // always from inside lock! + private + void start_() { + dispatchThread = new Thread(this, NAME); + dispatchThread.start(); + } + + // always from inside lock! + private void + stop_() { + WPARAM wparam = new WPARAM(0); + LPARAM lparam = new LPARAM(0); + User32.IMPL.SendMessage(hWnd, WM_QUIT, wparam, lparam); + + try { + // wait for the dispatch thread to quit (but only if we are not on the dispatch thread) + if (!Thread.currentThread().equals(dispatchThread)) { + dispatchThread.join(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + @SuppressWarnings("Java8MapApi") + public static + void addListener(final int messageId, final Listener listener) { + synchronized (messageIDs) { + List listeners = messageIDs.get(messageId); + if (listeners == null) { + listeners = new ArrayList(); + messageIDs.put(messageId, listeners); + } + + listeners.add(listener); + } + } + public static + void removeListener(final Listener listener) { + synchronized (messageIDs) { + for (Map.Entry> entry : messageIDs.entrySet()) { + List value = entry.getValue(); + if (value.remove(listener)) { + return; + } + } + } + } + + @Override + public + void run() { + WndProc = new WNDPROC() { + @Override + public + LRESULT callback(HWND hWnd, int msg, WPARAM wParam, LPARAM lParam) { + List listeners = null; + synchronized (messageIDs) { + listeners = messageIDs.get(msg); + if (listeners != null) { + // make a copy, in case a listener action modifies the message listener + listeners = new ArrayList(listeners); + } + } + + if (listeners != null) { + for (final Listener listener : listeners) { + if (listener != null) { + try { + listener.run(hWnd, wParam, lParam); + } catch (Exception e) { + logger.error("Error during listener execution.", e); + } + } + } + } + + return User32.IMPL.DefWindowProc(hWnd, msg, wParam, lParam); + } + }; + + hWnd = User32.IMPL.CreateWindowEx(0, "STATIC", NAME, 0, 0, 0, 0, 0, null, null, null, + null); + if (hWnd == null) { + throw new GetLastErrorException(); + } + + User32.IMPL.SetWindowLong(hWnd, User32.GWL_WNDPROC, WndProc); + + synchronized (lock) { + lock.notifyAll(); + } + + MSG msg = new MSG(); + while (User32.IMPL.GetMessage(msg, null, 0, 0)) { + User32.IMPL.TranslateMessage(msg); + User32.IMPL.DispatchMessage(msg); + } + + if (hWnd != null) { + if (!User32.IMPL.DestroyWindow(hWnd)) { + throw new GetLastErrorException(); + } + hWnd = null; + } + } +} diff --git a/src/dorkbox/util/jna/windows/structs/BLENDFUNCTION.java b/src/dorkbox/util/jna/windows/structs/BLENDFUNCTION.java new file mode 100644 index 0000000..b89dd9d --- /dev/null +++ b/src/dorkbox/util/jna/windows/structs/BLENDFUNCTION.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows.structs; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.WinUser; + +public class BLENDFUNCTION extends Structure { + public static class ByValue extends BLENDFUNCTION implements Structure.ByValue { + } + + public static class ByReference extends BLENDFUNCTION implements Structure.ByReference { + } + + public byte BlendOp = WinUser.AC_SRC_OVER; // only valid value + public byte BlendFlags = 0; // only valid value + public byte SourceConstantAlpha; + public byte AlphaFormat; + + public + BLENDFUNCTION() { + } + + @Override + protected + List getFieldOrder() { + return Arrays.asList("BlendOp", "BlendFlags", "SourceConstantAlpha", "AlphaFormat"); + } +} diff --git a/src/dorkbox/util/jna/windows/structs/DRAWITEMSTRUCT.java b/src/dorkbox/util/jna/windows/structs/DRAWITEMSTRUCT.java new file mode 100644 index 0000000..ffb710d --- /dev/null +++ b/src/dorkbox/util/jna/windows/structs/DRAWITEMSTRUCT.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows.structs; + +import static com.sun.jna.platform.win32.WinDef.HDC; +import static com.sun.jna.platform.win32.WinDef.HWND; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.BaseTSD; +import com.sun.jna.platform.win32.WinDef; + +/** + * http://msdn.microsoft.com/en-us/library/windows/desktop/bb775802(v=vs.85).aspx + */ +public class DRAWITEMSTRUCT extends Structure { + + public static class ByValue extends DRAWITEMSTRUCT implements Structure.ByValue { + } + + public static class ByReference extends DRAWITEMSTRUCT implements Structure.ByReference { + } + + public static final int ODT_BUTTON = 4; + public static final int ODT_COMBOBOX = 3; + public static final int ODT_LISTBOX = 2; + public static final int ODT_LISTVIEW = 102; + public static final int ODT_MENU = 1; + public static final int ODT_STATIC = 5; + public static final int ODT_TAB = 101; + + public static final int ODS_SELECTED = 1; + + public int CtlType; + public int CtlID; + public int itemID; + public int itemAction; + public int itemState; + public HWND hwndItem; + public HDC hDC; + public WinDef.RECT rcItem; + public BaseTSD.ULONG_PTR itemData; + + public DRAWITEMSTRUCT() { + } + + public DRAWITEMSTRUCT(Pointer p) { + super(p); + + read(); + } + + @Override + protected + List getFieldOrder() { + return Arrays.asList("CtlType", "CtlID", "itemID", "itemAction", "itemState", "hwndItem", "hDC", "rcItem", "itemData"); + } +} diff --git a/src/dorkbox/util/jna/windows/POINT.java b/src/dorkbox/util/jna/windows/structs/ICONINFO.java similarity index 51% rename from src/dorkbox/util/jna/windows/POINT.java rename to src/dorkbox/util/jna/windows/structs/ICONINFO.java index 44f204b..84f2148 100644 --- a/src/dorkbox/util/jna/windows/POINT.java +++ b/src/dorkbox/util/jna/windows/structs/ICONINFO.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 dorkbox, llc + * Copyright 2017 dorkbox, llc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package dorkbox.util.jna.windows; +package dorkbox.util.jna.windows.structs; + +import static com.sun.jna.platform.win32.WinDef.DWORD; +import static com.sun.jna.platform.win32.WinDef.HBITMAP; import java.util.Arrays; import java.util.List; @@ -21,44 +24,27 @@ import java.util.List; import com.sun.jna.Structure; /** - * https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms648052(v=vs.85).aspx */ public -class POINT extends Structure { - public long x; - public long y; +class ICONINFO extends Structure { + public boolean IsIcon; + public DWORD xHotspot; + public DWORD yHotspot; + public HBITMAP MaskBitmap; + public HBITMAP ColorBitmap; + public - POINT() { - } - - public - POINT(final long x, final long y) { - this.x = x; - this.y = y; - } - - public - POINT.ByValue asValue() { - POINT.ByValue copy = new POINT.ByValue(); - copy.x = this.x; - copy.y = this.y; - return copy; + ICONINFO() { } @Override protected List getFieldOrder() { - return Arrays.asList("x", "y"); + return Arrays.asList("IsIcon", "xHotspot", "yHotspot", "MaskBitmap", "ColorBitmap"); } - @Override - public - String toString() { - return x + ":" + y; - } - - - static public - class ByValue extends POINT implements Structure.ByValue {} + public static + class ByValue extends ICONINFO implements Structure.ByValue {} } diff --git a/src/dorkbox/util/jna/windows/structs/LOGFONT.java b/src/dorkbox/util/jna/windows/structs/LOGFONT.java new file mode 100644 index 0000000..7820e9e --- /dev/null +++ b/src/dorkbox/util/jna/windows/structs/LOGFONT.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows.structs; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.WinDef; + +/** + * https://msdn.microsoft.com/en-us/library/windows/desktop/dd145037(v=vs.85).aspx + */ +public class LOGFONT extends Structure { + + public static final int LF_FACESIZE = 32; + + public static class ByValue extends LOGFONT implements Structure.ByValue { + } + + public WinDef.LONG lfHeight; + public WinDef.LONG lfWidth; + public WinDef.LONG lfEscapement; + public WinDef.LONG lfOrientation; + public WinDef.LONG lfWeight; + public byte lfItalic; + public byte lfUnderline; + public byte lfStrikeOut; + public byte lfCharSet; + public byte lfOutPrecision; + public byte lfClipPrecision; + public byte lfQuality; + public byte lfPitchAndFamily; + public char[] lfFaceName = new char[LF_FACESIZE]; + + public LOGFONT() { + } + + public LOGFONT(Pointer p) { + super(p); + + read(); + } + + @Override + protected + List getFieldOrder() { + return Arrays.asList("lfHeight", + "lfWidth", + "lfEscapement", + "lfOrientation", + "lfWeight", + "lfItalic", + "lfUnderline", + "lfStrikeOut", + "lfCharSet", + "lfOutPrecision", + "lfClipPrecision", + "lfQuality", + "lfPitchAndFamily", + "lfFaceName"); + } +} diff --git a/src/dorkbox/util/jna/windows/structs/MEASUREITEMSTRUCT.java b/src/dorkbox/util/jna/windows/structs/MEASUREITEMSTRUCT.java new file mode 100644 index 0000000..c9b5ad2 --- /dev/null +++ b/src/dorkbox/util/jna/windows/structs/MEASUREITEMSTRUCT.java @@ -0,0 +1,62 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows.structs; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.BaseTSD; + +/** + * http://msdn.microsoft.com/en-us/library/windows/desktop/bb775804(v=vs.85).aspx + */ +public class MEASUREITEMSTRUCT extends Structure { + public static class ByValue extends MEASUREITEMSTRUCT implements Structure.ByValue { + } + + public static class ByReference extends MEASUREITEMSTRUCT implements Structure.ByReference { + } + + public static final int ODT_MENU = 1; + public static final int ODT_LISTBOX = 2; + public static final int ODT_COMBOBOX = 3; + public static final int ODT_BUTTON = 4; + public static final int ODT_STATIC = 5; + + public int CtlType; + public int CtlID; + public int itemID; + public int itemWidth; + public int itemHeight; + public BaseTSD.ULONG_PTR itemData; + + public MEASUREITEMSTRUCT() { + } + + public MEASUREITEMSTRUCT(Pointer p) { + super(p); + + read(); + } + + @Override + protected + List getFieldOrder() { + return Arrays.asList("CtlType", "CtlID", "itemID", "itemWidth", "itemHeight", "itemData"); + } +} diff --git a/src/dorkbox/util/jna/windows/structs/MENUITEMINFO.java b/src/dorkbox/util/jna/windows/structs/MENUITEMINFO.java new file mode 100644 index 0000000..a9be9e1 --- /dev/null +++ b/src/dorkbox/util/jna/windows/structs/MENUITEMINFO.java @@ -0,0 +1,89 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows.structs; + +import static com.sun.jna.platform.win32.BaseTSD.ULONG_PTR; +import static com.sun.jna.platform.win32.WinDef.HBITMAP; +import static com.sun.jna.platform.win32.WinDef.HMENU; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; + +/** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms647578(v=vs.85).aspx + */ +public +class MENUITEMINFO extends Structure { + + public static final int MFS_ENABLED = 0x00000000; + public static final int MFS_DISABLED = 0x00000003; + + public static final int MFS_GRAYED = 0x00000003; + public static final int MFS_DEFAULT = 0x00001000; + + public static final int MFS_CHECKED = 0x00000008; + public static final int MFS_UNCHECKED= 0x00000000; + + public static final int MFS_HILITE = 0x00000080; + public static final int MFS_UNHILITE = 0x00000000; + + public static final int MIIM_DATA = 0x00000020; + + + public int cbSize; + public int fMask; + public int fType; + public int fState; + public int wID; + + public HMENU hSubMenu; + public HBITMAP hbmpChecked; + public HBITMAP hbmpUnchecked; + public ULONG_PTR dwItemData; + public String dwTypeData; + public int cch; + public HBITMAP hbmpItem; + + public + MENUITEMINFO() { + cbSize = size(); + } + + public + MENUITEMINFO(Pointer p) { + super(p); + } + + @Override + protected + List getFieldOrder() { + return Arrays.asList("cbSize", + "fMask", + "fType", + "fState", + "wID", + "hSubMenu", + "hbmpChecked", + "hbmpUnchecked", + "dwItemData", + "dwTypeData", + "cch", + "hbmpItem"); + } +} diff --git a/src/dorkbox/util/jna/windows/structs/NONCLIENTMETRICS.java b/src/dorkbox/util/jna/windows/structs/NONCLIENTMETRICS.java new file mode 100644 index 0000000..ba03693 --- /dev/null +++ b/src/dorkbox/util/jna/windows/structs/NONCLIENTMETRICS.java @@ -0,0 +1,88 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows.structs; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Pointer; +import com.sun.jna.Structure; + +/** + * http://msdn.microsoft.com/en-us/library/windows/desktop/ff729175(v=vs.85).aspx + */ +public class NONCLIENTMETRICS extends Structure { + public static class ByValue extends NONCLIENTMETRICS implements Structure.ByValue { + } + + public static class ByReference extends NONCLIENTMETRICS implements Structure.ByReference { + } + + public static final int ODT_MENU = 1; + public static final int ODT_LISTBOX = 2; + public static final int ODT_COMBOBOX = 3; + public static final int ODT_BUTTON = 4; + public static final int ODT_STATIC = 5; + + public int cbSize; + public int iBorderWidth; + public int iScrollWidth; + public int iScrollHeight; + public int iCaptionWidth; + public int iCaptionHeight; + public LOGFONT.ByValue lfCaptionFont; + public int iSmCaptionWidth; + public int iSmCaptionHeight; + public LOGFONT.ByValue lfSmCaptionFont; + public int iMenuWidth; + public int iMenuHeight; + public LOGFONT.ByValue lfMenuFont; + public LOGFONT.ByValue lfStatusFont; + public LOGFONT.ByValue lfMessageFont; + //public int iPaddedBorderWidth; + + public NONCLIENTMETRICS() { + cbSize = size(); + } + + public NONCLIENTMETRICS(Pointer p) { + super(p); + + read(); + } + + @Override + protected + List getFieldOrder() { + return Arrays.asList("cbSize", + "iBorderWidth", + "iScrollWidth", + "iScrollHeight", + "iCaptionWidth", + "iCaptionHeight", + "lfCaptionFont", + "iSmCaptionWidth", + "iSmCaptionHeight", + "lfSmCaptionFont", + "iMenuWidth", + "iMenuHeight", + "lfMenuFont", + "lfStatusFont", + "lfMessageFont" + //"iPaddedBorderWidth" + ); + } +} diff --git a/src/dorkbox/util/jna/windows/structs/NOTIFYICONDATA.java b/src/dorkbox/util/jna/windows/structs/NOTIFYICONDATA.java new file mode 100644 index 0000000..d41ca4b --- /dev/null +++ b/src/dorkbox/util/jna/windows/structs/NOTIFYICONDATA.java @@ -0,0 +1,116 @@ +/* + * Copyright 2017 dorkbox, llc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package dorkbox.util.jna.windows.structs; + +import static com.sun.jna.platform.win32.WinDef.HWND; + +import java.util.Arrays; +import java.util.List; + +import com.sun.jna.Structure; +import com.sun.jna.platform.win32.WinDef; + +/** + * http://msdn.microsoft.com/en-us/library/windows/desktop/bb773352(v=vs.85).aspx + */ +public class NOTIFYICONDATA extends Structure { + static public final int NIF_MESSAGE = 0x1; + static public final int NIF_ICON = 0x2; + static public final int NIF_TIP = 0x4; + static public final int NIF_STATE = 0x8; + + static public final int NIF_INFO = 0x10; + + static public final int NIIF_NONE = 0x0; + static public final int NIIF_INFO = 0x1; + static public final int NIIF_WARNING = 0x2; + static public final int NIIF_ERROR = 0x3; + static public final int NIIF_USER = 0x4; + + public int cbSize; + public HWND hWnd; + public int uID; + public int uFlags; + public int uCallbackMessage; + public WinDef.HICON hIcon; + + public char[] szTip = new char[128]; + + public int dwState; + public int dwStateMask; + + public char[] szInfo = new char[256]; + public int uTimeoutOrVersion; // {UINT uTimeout; UINT uVersion;}; + + public char[] szInfoTitle = new char[64]; + public int dwInfoFlags; + + public + NOTIFYICONDATA() { + cbSize = size(); + } + + public + void setTooltip(String s) { + uFlags |= NIF_TIP; + + System.arraycopy(s.toCharArray(), 0, szTip, 0, Math.min(s.length(), szTip.length)); + szTip[s.length()] = '\0'; + } + + public + void setBalloon(String title, String message, int millis, int niif) { + uFlags |= NIF_INFO; + + System.arraycopy(message.toCharArray(), 0, szInfo, 0, Math.min(message.length(), szInfo.length)); + szInfo[message.length()] = '\0'; + + uTimeoutOrVersion = millis; + + System.arraycopy(title.toCharArray(), 0, szInfoTitle, 0, Math.min(title.length(), szInfoTitle.length)); + szInfoTitle[title.length()] = '\0'; + + dwInfoFlags = niif; + } + + public + void setIcon(WinDef.HICON hIcon) { + uFlags |= NIF_ICON; + this.hIcon = hIcon; + } + + public void setCallback(int callback) { + uFlags |= NIF_MESSAGE; + uCallbackMessage = callback; + } + + @Override + protected List getFieldOrder () { + return Arrays.asList("cbSize", + "hWnd", + "uID", + "uFlags", + "uCallbackMessage", + "hIcon", + "szTip", + "dwState", + "dwStateMask", + "szInfo", + "uTimeoutOrVersion", + "szInfoTitle", + "dwInfoFlags"); + } +}