# HG changeset patch # User Frank Benoit # Date 1211038468 -7200 # Node ID 36f5cb12e1a276212ca61488f12ff1f8c5b0b671 # Parent ab60f33094366d9f23801d363a10e645bc910138 Update to SWT 3.4M7 diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/DWT.d --- a/dwt/DWT.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/DWT.d Sat May 17 17:34:28 2008 +0200 @@ -640,9 +640,76 @@ */ public static const int PaintItem = 42; + /** + * The IME composition event type (value is 43). + *

+ * The IME composition event is sent to allow + * custom text editors to implement in-line + * editing of international text. + *

+ * + * The detail field indicates the action to be taken: + *

+ * + * @see dwt.widgets.Widget#addListener + * @see dwt.widgets.Display#addFilter + * @see dwt.widgets.Event + * + * @since 3.4 + */ + public static const int ImeComposition = 43; + /* Event Details */ /** + * The IME composition event detail that indicates + * a change in the IME composition. The text field + * of the event is the new composition text. + * The start and end indicate the offsets where the + * composition text should be inserted. + * The styles and ranges are stored in the IME + * object (value is 1). + * + * @see DWT#ImeComposition + * + * @since 3.4 + */ + public static const int COMPOSITION_CHANGED = 1; + + /** + * The IME composition event detail that indicates + * that the IME needs the offset for a given location. + * The x and y fields of the event are used by the + * application to determine the offset. + * + * The index field of the event should be set to the + * text offset at that location. The count field should + * be set to indicate whether the location is closer to + * the leading edge (0) or the trailing edge (1) (value is 2). + * + * @see DWT#ImeComposition + * @see dwt.graphics.TextLayout#getOffset(int, int, int[]) + * + * @since 3.4 + */ + public static const int COMPOSITION_OFFSET = 2; + + /** + * The IME composition event detail that indicates + * that IME needs the selected text and its start + * and end offsets (value is 3). + * + * @see DWT#ImeComposition + * + * @since 3.4 + */ + public static const int COMPOSITION_SELECTION = 3; + + /** * Indicates that a user-interface component is being dragged, * for example dragging the thumb of a scroll bar (value is 1). */ @@ -1135,6 +1202,23 @@ public static const int V_SCROLL = 1 << 9; /** + * Style constant for no scrollbar behavior (value is 1<<4). + *

+ * When neither H_SCROLL or V_SCROLL are specified, controls + * are free to create the default scroll bars for the control. + * Using NO_SCROLL overrides the default and forces the control + * to have no scroll bars. + * + * Used By:

+ * + * @since 3.4 + */ + public static const int NO_SCROLL = 1 << 4; + + /** * Style constant for bordered behavior (value is 1<<11). *
Note that this is a HINT. *

Used By:

* * @see DropTargetListener + * @see #getDropListeners * @see #removeDropListener * @see DropTargetEvent */ @@ -259,6 +260,12 @@ iDropTarget = null; } +int DragEnter_64(IDataObject pDataObject, DWORD grfKeyState, long pt, DWORD* pdwEffect) { + POINTL point; + OS.MoveMemory( &point, &pt, 8); + return DragEnter(pDataObject, grfKeyState, point, pdwEffect); +} + HRESULT DragEnter(IDataObject pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect) { selectedDataType = null; selectedOperation = DND.DROP_NONE; @@ -318,6 +325,12 @@ return COM.S_OK; } +int DragOver_64(int grfKeyState, long pt, DWORD* pdwEffect) { + POINTL point; + OS.MoveMemory(&point, &pt, 8); + return DragOver(grfKeyState, point, pdwEffect); +} + HRESULT DragOver(int grfKeyState, POINTL pt, DWORD* pdwEffect) { if (iDataObject is null) return COM.S_FALSE; int oldKeyOperation = keyOperation; @@ -364,6 +377,12 @@ return COM.S_OK; } +int Drop_64(IDataObject pDataObject, int grfKeyState, long pt, DWORD* pdwEffect) { + POINTL point; + OS.MoveMemory(&point, &pt, 8); + return Drop(pDataObject, grfKeyState, point, pdwEffect); +} + HRESULT Drop(IDataObject pDataObject, int grfKeyState, POINTL pt, DWORD* pdwEffect) { DNDEvent event = new DNDEvent(); event.widget = this; @@ -450,6 +469,41 @@ } /** + * Returns an array of listeners who will be notified when a drag and drop + * operation is in progress, by sending it one of the messages defined in + * the DropTargetListener interface. + * + * @exception DWTException + * + * @see DropTargetListener + * @see #addDropListener + * @see #removeDropListener + * @see DropTargetEvent + * + * @since 3.4 + */ +public DropTargetListener[] getDropListeners() { + Listener[] listeners = getListeners(DND.DragEnter); + int length = listeners.length; + DropTargetListener[] dropListeners = new DropTargetListener[length]; + int count = 0; + for (int i = 0; i < length; i++) { + Listener listener = listeners[i]; + if (auto l = cast(DNDListener)listener ) { + dropListeners[count] = cast(DropTargetListener) (l.getEventListener()); + count++; + } + } + if (count is length) return dropListeners; + DropTargetListener[] result = new DropTargetListener[count]; + SimpleType!(DropTargetListener).arraycopy(dropListeners, 0, result, 0, count); + return result; +} + +/** * Returns the drop effect for this DropTarget. This drop effect will be * used during a drag and drop to display the drag under effect on the * target widget. @@ -493,7 +547,7 @@ if (controlListener !is null) control.removeListener(DWT.Dispose, controlListener); controlListener = null; - control.setData(DROPTARGETID, null); + control.setData(DND.DROP_TARGET_KEY, null); transferAgents = null; control = null; @@ -588,6 +642,7 @@ * * @see DropTargetListener * @see #addDropListener + * @see #getDropListeners */ public void removeDropListener(DropTargetListener listener) { if (listener is null) DND.error (DWT.ERROR_NULL_ARGUMENT); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/dnd/DropTargetEffect.d --- a/dwt/dnd/DropTargetEffect.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/dnd/DropTargetEffect.d Sat May 17 17:34:28 2008 +0200 @@ -17,8 +17,8 @@ import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.widgets.Control; -import dwt.widgets.Item; import dwt.widgets.Table; +import dwt.widgets.TableItem; import dwt.widgets.Tree; import dwt.widgets.TreeItem; import dwt.widgets.Widget; @@ -107,38 +107,39 @@ Widget getItem(Table table, int x, int y) { Point coordinates = new Point(x, y); coordinates = table.toControl(coordinates); - Item item = table.getItem(coordinates); - if (item is null) { - Rectangle area = table.getClientArea(); - if (area.contains(coordinates)) { - // Scan across the width of the table. - for (int x1 = area.x; x1 < area.x + area.width; x1++) { - Point pt = new Point(x1, coordinates.y); - item = table.getItem(pt); - if (item !is null) { - break; - } - } - } + TableItem item = table.getItem(coordinates); + if (item !is null) return item; + Rectangle area = table.getClientArea(); + int tableBottom = area.y + area.height; + int itemCount = table.getItemCount(); + for (int i=table.getTopIndex(); i tableBottom) break; } - return item; + return null; } Widget getItem(Tree tree, int x, int y) { - Point coordinates = new Point(x, y); - coordinates = tree.toControl(coordinates); - Item item = tree.getItem(coordinates); + Point point = new Point(x, y); + point = tree.toControl(point); + TreeItem item = tree.getItem(point); if (item is null) { Rectangle area = tree.getClientArea(); - if (area.contains(coordinates)) { - // Scan across the width of the tree. - for (int x1 = area.x; x1 < area.x + area.width; x1++) { - Point pt = new Point(x1, coordinates.y); - item = tree.getItem(pt); - if (item !is null) { - break; - } + if (area.contains(point)) { + int treeBottom = area.y + area.height; + item = tree.getTopItem(); + while (item !is null) { + Rectangle rect = item.getBounds(); + int itemBottom = rect.y + rect.height; + if (rect.y <= point.y && point.y < itemBottom) return item; + if (itemBottom > treeBottom) break; + item = nextItem(tree, item); } + return null; } } return item; @@ -146,7 +147,7 @@ TreeItem nextItem(Tree tree, TreeItem item) { if (item is null) return null; - if (item.getExpanded()) return item.getItem(0); + if (item.getExpanded() && item.getItemCount() > 0) return item.getItem(0); TreeItem childItem = item; TreeItem parentItem = childItem.getParentItem(); int index = parentItem is null ? tree.indexOf(childItem) : parentItem.indexOf(childItem); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/dnd/HTMLTransfer.d --- a/dwt/dnd/HTMLTransfer.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/dnd/HTMLTransfer.d Sat May 17 17:34:28 2008 +0200 @@ -85,8 +85,8 @@ DND.error(DND.ERROR_INVALID_DATA); } String string = ( cast(ArrayWrapperString)object ).array; - int codePage = OS.GetACP(); - int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, StrToTCHARz(string), -1, null, 0, null, null); + /* NOTE: CF_HTML uses UTF-8 encoding. */ + int cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, StrToTCHARz(string), -1, null, 0, null, null); if (cchMultiByte is 0) { transferData.stgmedium = new STGMEDIUM(); transferData.result = COM.DV_E_STGMEDIUM; @@ -130,10 +130,10 @@ buffer.append(string); buffer.append(SUFFIX); - auto wstrz = StrToTCHARz(codePage,buffer.toString); - cchMultiByte = OS.WideCharToMultiByte(codePage, 0, wstrz, -1, null, 0, null, null); + auto wstrz = StrToTCHARz(OS.CP_UTF8,buffer.toString); + cchMultiByte = OS.WideCharToMultiByte(OS.CP_UTF8, 0, wstrz, -1, null, 0, null, null); auto lpMultiByteStr = cast(char*) OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte); - OS.WideCharToMultiByte(codePage, 0, wstrz, -1, lpMultiByteStr, cchMultiByte, null, null); + OS.WideCharToMultiByte(OS.CP_UTF8, 0, wstrz, -1, lpMultiByteStr, cchMultiByte, null, null); transferData.stgmedium = new STGMEDIUM(); transferData.stgmedium.tymed = COM.TYMED_HGLOBAL; transferData.stgmedium.unionField = lpMultiByteStr; @@ -168,11 +168,13 @@ auto lpMultiByteStr = cast(char*) OS.GlobalLock(hMem); if (lpMultiByteStr is null) return null; try { - int codePage = OS.GetACP(); - auto cchWideChar = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0); + /* NOTE: CF_HTML uses UTF-8 encoding. + * The MSDN documentation for MultiByteToWideChar states that dwFlags must be set to 0 for UTF-8. + * Otherwise, the function fails with ERROR_INVALID_FLAGS. */ + auto cchWideChar = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, null, 0); if (cchWideChar is 0) return null; wchar[] lpWideCharStr = new wchar [cchWideChar - 1]; - OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length); + OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length); String string = WCHARzToStr(lpWideCharStr.ptr); int fragmentStart = 0, fragmentEnd = 0; int start = string.indexOf(StartFragment) + StartFragment.length; @@ -197,12 +199,10 @@ break; } } - if (fragmentEnd <= fragmentStart || fragmentEnd > lpWideCharStr.length) return null; - /* TO DO: - * FragmentStart and FragmentEnd are offsets in original byte stream, not - * the wide char version of the byte stream. - */ - String s = string.substring(fragmentStart, fragmentEnd); + if (fragmentEnd <= fragmentStart || fragmentEnd > OS.strlen(lpMultiByteStr)) return null; + cchWideChar = OS.MultiByteToWideChar (OS.CP_UTF8, 0, lpMultiByteStr+fragmentStart, fragmentEnd - fragmentStart, lpWideCharStr.ptr, lpWideCharStr.length); + if (cchWideChar is 0) return null; + String s = TCHARsToStr( lpWideCharStr[ 0 .. cchWideChar ] ); /* * Firefox includes in the fragment, so remove it. */ diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/dnd/ImageTransfer.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/ImageTransfer.d Sat May 17 17:34:28 2008 +0200 @@ -0,0 +1,224 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.dnd.ImageTransfer; + +import dwt.DWT; +import dwt.graphics.Image; +import dwt.graphics.ImageData; +import dwt.graphics.RGB; +import dwt.internal.win32.OS; +import dwt.internal.ole.win32.COM; +import dwt.internal.ole.win32.OBJIDL; + +import dwt.dnd.ByteArrayTransfer; +import dwt.dnd.TransferData; +import dwt.dnd.DND; + +import dwt.dwthelper.utils; + +/** + * The class ImageTransfer provides a platform specific mechanism + * for converting a Image represented as a java ImageData to a + * platform specific representation of the data and vice versa. + * See Transfer for additional information. + * + *

An example of a java ImageData is shown + * below:

+ * + *
+ *     Image image = new Image("C:\temp\img1.gif");
+ *     ImageData imgData = image.getImageData();
+ * 
+ * + * @since 3.4 + */ +public class ImageTransfer : ByteArrayTransfer { + + private static ImageTransfer _instance; + private static const String CF_DIB = "CF_DIB"; //$NON-NLS-1$ + private static const int CF_DIBID = COM.CF_DIB; + +static this(){ + _instance = new ImageTransfer(); +} + +private this() { +} + +/** + * Returns the singleton instance of the ImageTransfer class. + * + * @return the singleton instance of the ImageTransfer class + */ +public static ImageTransfer getInstance () { + return _instance; +} + +/** + * This implementation of javaToNative converts an ImageData object represented + * by java ImageData to a platform specific representation. + * For additional information see Transfer#javaToNative. + * + * @param object a java ImageData containing the ImageData to be + * converted + * @param transferData an empty TransferData object; this + * object will be filled in on return with the platform specific format of the data + */ +public void javaToNative(Object object, TransferData transferData) { + if (!checkImage(object) || !isSupportedType(transferData)) { + DND.error(DND.ERROR_INVALID_DATA); + } + ImageData imgData = cast(ImageData)object; + if (imgData is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + + int imageSize = imgData.data.length; + int imageHeight = imgData.height; + int bytesPerLine = imgData.bytesPerLine; + + BITMAPINFOHEADER bmiHeader; + bmiHeader.biSize = BITMAPINFOHEADER.sizeof; + bmiHeader.biSizeImage = imageSize; + bmiHeader.biWidth = imgData.width; + bmiHeader.biHeight = imageHeight; + bmiHeader.biPlanes = 1; + bmiHeader.biBitCount = cast(short)imgData.depth; + bmiHeader.biCompression = OS.DIB_RGB_COLORS; + + int colorSize = 0; + if (bmiHeader.biBitCount <= 8) { + colorSize += (1 << bmiHeader.biBitCount) * 4; + } + byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + colorSize]; + OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof); + + RGB[] rgbs = imgData.palette.getRGBs(); + if (rgbs !is null && colorSize > 0) { + int offset = BITMAPINFOHEADER.sizeof; + for (int j = 0; j < rgbs.length; j++) { + bmi[offset] = cast(byte)rgbs[j].blue; + bmi[offset + 1] = cast(byte)rgbs[j].green; + bmi[offset + 2] = cast(byte)rgbs[j].red; + bmi[offset + 3] = 0; + offset += 4; + } + } + auto newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, BITMAPINFOHEADER.sizeof + colorSize + imageSize); + OS.MoveMemory(newPtr, bmi.ptr, bmi.length); + auto pBitDest = newPtr + BITMAPINFOHEADER.sizeof + colorSize; + + if (imageHeight <= 0) { + OS.MoveMemory(pBitDest, imgData.data.ptr, imageSize); + } else { + int offset = 0; + pBitDest += bytesPerLine * (imageHeight - 1); + byte[] scanline = new byte[bytesPerLine]; + for (int i = 0; i < imageHeight; i++) { + System.arraycopy(imgData.data, offset, scanline, 0, bytesPerLine); + OS.MoveMemory(pBitDest, scanline.ptr, bytesPerLine); + offset += bytesPerLine; + pBitDest -= bytesPerLine; + } + } + transferData.stgmedium = new STGMEDIUM(); + transferData.stgmedium.tymed = COM.TYMED_HGLOBAL; + transferData.stgmedium.unionField = newPtr; + transferData.stgmedium.pUnkForRelease = null; + transferData.result = COM.S_OK; +} + + +/** + * This implementation of nativeToJava converts a platform specific + * representation of an image to java ImageData. + * For additional information see Transfer#nativeToJava. + * + * @param transferData the platform specific representation of the data to be + * been converted + * @return a java ImageData of the image if + * conversion was successful; otherwise null + */ +public Object nativeToJava(TransferData transferData) { + if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null; + IDataObject dataObject = cast(IDataObject)(transferData.pIDataObject); + dataObject.AddRef(); + FORMATETC* formatetc = new FORMATETC(); + formatetc.cfFormat = COM.CF_DIB; + formatetc.ptd = null; + formatetc.dwAspect = COM.DVASPECT_CONTENT; + formatetc.lindex = -1; + formatetc.tymed = COM.TYMED_HGLOBAL; + STGMEDIUM* stgmedium = new STGMEDIUM(); + stgmedium.tymed = COM.TYMED_HGLOBAL; + transferData.result = dataObject.GetData(formatetc, stgmedium); + + if (transferData.result !is COM.S_OK) return null; + HANDLE hMem = stgmedium.unionField; + dataObject.Release(); + try { + auto ptr = OS.GlobalLock(hMem); + if (ptr is null) return null; + try { + BITMAPINFOHEADER bmiHeader; + OS.MoveMemory(&bmiHeader, ptr, BITMAPINFOHEADER.sizeof); + void* pBits; + auto memDib = OS.CreateDIBSection(null, cast(BITMAPINFO*)ptr, OS.DIB_RGB_COLORS, &pBits, null, 0); + if (memDib is null) DWT.error(DWT.ERROR_NO_HANDLES); + void* bits = ptr + bmiHeader.biSize; + if (bmiHeader.biBitCount <= 8) { + bits += (1 << bmiHeader.biBitCount) * 4; + } else if (bmiHeader.biCompression is OS.BI_BITFIELDS) { + bits += 12; + } + if (bmiHeader.biHeight < 0) { + OS.MoveMemory(pBits, bits, bmiHeader.biSizeImage); + } else { + DIBSECTION dib; + OS.GetObject(memDib, DIBSECTION.sizeof, &dib); + int biHeight = dib.biHeight; + int scanline = dib.biSizeImage / biHeight; + auto pDestBits = pBits; + auto pSourceBits = bits + scanline * (biHeight - 1); + for (int i = 0; i < biHeight; i++) { + OS.MoveMemory(pDestBits, pSourceBits, scanline); + pDestBits += scanline; + pSourceBits -= scanline; + } + } + Image image = Image.win32_new(null, DWT.BITMAP, memDib); + ImageData data = image.getImageData(); + OS.DeleteObject(memDib); + image.dispose(); + return data; + } finally { + OS.GlobalUnlock(hMem); + } + } finally { + OS.GlobalFree(hMem); + } +} + +protected int[] getTypeIds(){ + return [CF_DIBID]; +} + +protected String[] getTypeNames(){ + return [CF_DIB]; +} +bool checkImage(Object object) { + if (object is null || !(null !is cast(ImageData)object )) return false; + return true; +} + +protected bool validate(Object object) { + return checkImage(object); +} +} + diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/dnd/OleEnumFORMATETC.d --- a/dwt/dnd/OleEnumFORMATETC.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/dnd/OleEnumFORMATETC.d Sat May 17 17:34:28 2008 +0200 @@ -15,6 +15,7 @@ import dwt.internal.ole.win32.COM; import dwt.internal.ole.win32.OBJIDL; import dwt.internal.ole.win32.extras; +import dwt.internal.win32.OS; final class OleEnumFORMATETC { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/dnd/TableDragSourceEffect.d --- a/dwt/dnd/TableDragSourceEffect.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/dnd/TableDragSourceEffect.d Sat May 17 17:34:28 2008 +0200 @@ -14,6 +14,8 @@ import dwt.DWT; import dwt.graphics.Image; +import dwt.graphics.ImageData; +import dwt.graphics.PaletteData; import dwt.graphics.Rectangle; import dwt.internal.win32.OS; import dwt.widgets.Display; @@ -87,10 +89,78 @@ Image getDragSourceImage(DragSourceEvent event) { if (dragSourceImage !is null) dragSourceImage.dispose(); dragSourceImage = null; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { + SHDRAGIMAGE shdi; + int DI_GETDRAGIMAGE = OS.RegisterWindowMessage ( "ShellGetDragImage"w.ptr ); //$NON-NLS-1$ + if (OS.SendMessage (control.handle, DI_GETDRAGIMAGE, 0, &shdi) !is 0) { + event.x += shdi.ptOffset.x; + event.y += shdi.ptOffset.y; + auto hImage = shdi.hbmpDragImage; + if (hImage !is null) { + BITMAP bm; + OS.GetObject (hImage, BITMAP.sizeof, &bm); + int srcWidth = bm.bmWidth; + int srcHeight = bm.bmHeight; + + /* Create resources */ + auto hdc = OS.GetDC (null); + auto srcHdc = OS.CreateCompatibleDC (hdc); + auto oldSrcBitmap = OS.SelectObject (srcHdc, hImage); + auto memHdc = OS.CreateCompatibleDC (hdc); + BITMAPINFOHEADER bmiHeader; + bmiHeader.biSize = BITMAPINFOHEADER.sizeof; + bmiHeader.biWidth = srcWidth; + bmiHeader.biHeight = -srcHeight; + bmiHeader.biPlanes = 1; + bmiHeader.biBitCount = 32; + bmiHeader.biCompression = OS.BI_RGB; + void* pBits; + auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)&bmiHeader, OS.DIB_RGB_COLORS, &pBits, null, 0); + if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES); + auto oldMemBitmap = OS.SelectObject (memHdc, memDib); + + BITMAP dibBM; + OS.GetObject (memDib, BITMAP.sizeof, &dibBM); + int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight; + + /* Get the foreground pixels */ + OS.BitBlt (memHdc, 0, 0, srcWidth, srcHeight, srcHdc, 0, 0, OS.SRCCOPY); + //byte[] srcData = new byte [sizeInBytes]; + //OS.MoveMemory (srcData, dibBM.bmBits, sizeInBytes); + byte[] srcData = (cast(byte*) dibBM.bmBits)[ 0 .. BITMAPINFOHEADER.sizeof ]; + + byte[] alphaData = new byte[srcWidth * srcHeight]; + int spinc = dibBM.bmWidthBytes - srcWidth * 4; + int ap = 0, sp = 3; + for (int y = 0; y < srcHeight; ++y) { + for (int x = 0; x < srcWidth; ++x) { + alphaData [ap++] = srcData [sp]; + sp += 4; + } + sp += spinc; + } + PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); + ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData); + data.alphaData = alphaData; + data.transparentPixel = shdi.crColorKey; + dragSourceImage = new Image(control.getDisplay(), data); + OS.SelectObject (memHdc, oldMemBitmap); + OS.DeleteDC (memHdc); + OS.DeleteObject (memDib); + OS.SelectObject (srcHdc, oldSrcBitmap); + OS.DeleteDC (srcHdc); + OS.ReleaseDC (null, hdc); + return dragSourceImage; + } + } + return null; + } Table table = cast(Table) control; + //TEMPORARY CODE + if (table.isListening (DWT.EraseItem) || table.isListening (DWT.PaintItem)) return null; TableItem[] selection = table.getSelection(); if (selection.length is 0) return null; - int tableImageList = OS.SendMessage (table.handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0); + int /*long*/ tableImageList = OS.SendMessage (table.handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0); if (tableImageList !is 0) { int count = Math.min(selection.length, 10); Rectangle bounds = selection[0].getBounds(0); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/dnd/TreeDragSourceEffect.d --- a/dwt/dnd/TreeDragSourceEffect.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/dnd/TreeDragSourceEffect.d Sat May 17 17:34:28 2008 +0200 @@ -14,6 +14,8 @@ import dwt.DWT; import dwt.graphics.Image; +import dwt.graphics.ImageData; +import dwt.graphics.PaletteData; import dwt.graphics.Rectangle; import dwt.internal.win32.OS; import dwt.widgets.Display; @@ -86,10 +88,66 @@ Image getDragSourceImage(DragSourceEvent event) { if (dragSourceImage !is null) dragSourceImage.dispose(); dragSourceImage = null; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { + SHDRAGIMAGE shdi; + int DI_GETDRAGIMAGE = OS.RegisterWindowMessage ("ShellGetDragImage"w.ptr); //$NON-NLS-1$ + if (OS.SendMessage (control.handle, DI_GETDRAGIMAGE, 0, &shdi) !is 0) { + event.x += shdi.ptOffset.x; + event.y += shdi.ptOffset.y; + auto hImage = shdi.hbmpDragImage; + if (hImage !is null) { + BITMAP bm; + OS.GetObject (hImage, BITMAP.sizeof, &bm); + int srcWidth = bm.bmWidth; + int srcHeight = bm.bmHeight; + + /* Create resources */ + auto hdc = OS.GetDC (null); + auto srcHdc = OS.CreateCompatibleDC (hdc); + auto oldSrcBitmap = OS.SelectObject (srcHdc, hImage); + auto memHdc = OS.CreateCompatibleDC (hdc); + BITMAPINFOHEADER bmiHeader; + bmiHeader.biSize = BITMAPINFOHEADER.sizeof; + bmiHeader.biWidth = srcWidth; + bmiHeader.biHeight = -srcHeight; + bmiHeader.biPlanes = 1; + bmiHeader.biBitCount = 32; + bmiHeader.biCompression = OS.BI_RGB; + void* pBits; + auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)&bmiHeader, OS.DIB_RGB_COLORS, &pBits, null, 0); + if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES); + auto oldMemBitmap = OS.SelectObject (memHdc, memDib); + + BITMAP dibBM; + OS.GetObject (memDib, BITMAP.sizeof, &dibBM); + int sizeInBytes = dibBM.bmWidthBytes * dibBM.bmHeight; + + /* Get the foreground pixels */ + OS.BitBlt (memHdc, 0, 0, srcWidth, srcHeight, srcHdc, 0, 0, OS.SRCCOPY); + byte[] srcData = (cast(byte*)dibBM.bmBits)[ 0 .. sizeInBytes ]; + + PaletteData palette = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); + ImageData data = new ImageData(srcWidth, srcHeight, bm.bmBitsPixel, palette, bm.bmWidthBytes, srcData); + data.transparentPixel = shdi.crColorKey << 8; + dragSourceImage = new Image (control.getDisplay (), data); + OS.SelectObject (memHdc, oldMemBitmap); + OS.DeleteDC (memHdc); + OS.DeleteObject (memDib); + OS.SelectObject (srcHdc, oldSrcBitmap); + OS.DeleteDC (srcHdc); + OS.ReleaseDC (null, hdc); + return dragSourceImage; + } + } + return null; + } + Tree tree = cast(Tree) control; + //TEMPORARY CODE + if (tree.isListening (DWT.EraseItem) || tree.isListening (DWT.PaintItem)) return null; TreeItem[] selection = tree.getSelection(); if (selection.length is 0) return null; - int treeImageList = OS.SendMessage (tree.handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0); + auto treeImageList = OS.SendMessage (tree.handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0); if (treeImageList !is 0) { int count = Math.min(selection.length, 10); Rectangle bounds = selection[0].getBounds(0); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/dnd/TreeDropTargetEffect.d --- a/dwt/dnd/TreeDropTargetEffect.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/dnd/TreeDropTargetEffect.d Sat May 17 17:34:28 2008 +0200 @@ -12,8 +12,10 @@ *******************************************************************************/ module dwt.dnd.TreeDropTargetEffect; +import dwt.DWT; import dwt.graphics.Point; import dwt.internal.win32.OS; +import dwt.widgets.Event; import dwt.widgets.Tree; import dwt.widgets.TreeItem; @@ -59,10 +61,10 @@ static final int SCROLL_HYSTERESIS = 200; // milli seconds static final int EXPAND_HYSTERESIS = 1000; // milli seconds - int dropIndex; + int /*long*/ dropIndex; int scrollIndex; long scrollBeginTime; - int expandIndex; + int /*long*/ expandIndex; long expandBeginTime; TreeItem insertItem; bool insertBefore; @@ -171,22 +173,21 @@ lpht.pt.x = coordinates.x; lpht.pt.y = coordinates.y; OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); - int hItem = cast(int) lpht.hItem; + auto hItem = lpht.hItem; if ((effect & DND.FEEDBACK_SCROLL) is 0) { scrollBeginTime = 0; scrollIndex = -1; } else { - if (hItem !is -1 && scrollIndex is hItem && scrollBeginTime !is 0) { + if (hItem !is cast(HTREEITEM)-1 && cast(HTREEITEM)scrollIndex is hItem && scrollBeginTime !is 0) { if (System.currentTimeMillis() >= scrollBeginTime) { - int topItem = OS.SendMessage(handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); - int nextItem = OS.SendMessage(handle, OS.TVM_GETNEXTITEM, hItem is topItem ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE, hItem); + auto topItem = cast(HTREEITEM)OS.SendMessage(handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); + auto nextItem = cast(HTREEITEM)OS.SendMessage(handle, OS.TVM_GETNEXTITEM, hItem is topItem ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE, hItem); bool scroll = true; if (hItem is topItem) { - scroll = nextItem !is 0; + scroll = nextItem !is null; } else { RECT itemRect; - itemRect.left = nextItem; - if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) { + if (OS.TreeView_GetItemRect (handle, nextItem, &itemRect, true)) { RECT rect; OS.GetClientRect (handle, &rect); POINT pt; @@ -207,23 +208,23 @@ } } else { scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS; - scrollIndex = hItem; + scrollIndex = cast(int)hItem; } } if ((effect & DND.FEEDBACK_EXPAND) is 0) { expandBeginTime = 0; expandIndex = -1; } else { - if (hItem !is -1 && expandIndex is hItem && expandBeginTime !is 0) { + if (cast(int)hItem !is -1 && expandIndex is cast(int)hItem && expandBeginTime !is 0) { if (System.currentTimeMillis() >= expandBeginTime) { if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem) !is 0) { - TVITEM tvItem; - tvItem.hItem = cast(HANDLE) hItem; - tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; - OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem); - if ((tvItem.state & OS.TVIS_EXPANDED) is 0) { - OS.SendMessage (handle, OS.TVM_EXPAND, OS.TVE_EXPAND, hItem); + TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, cast(int)hItem); + if (item !is null && !item.getExpanded()) { + item.setExpanded(true); tree.redraw(); + Event expandEvent = new Event (); + expandEvent.item = item; + tree.notifyListeners(DWT.Expand, expandEvent); } } expandBeginTime = 0; @@ -231,10 +232,10 @@ } } else { expandBeginTime = System.currentTimeMillis() + EXPAND_HYSTERESIS; - expandIndex = hItem; + expandIndex = cast(int)hItem; } } - if (dropIndex !is -1 && (dropIndex !is hItem || (effect & DND.FEEDBACK_SELECT) is 0)) { + if (dropIndex !is -1 && (dropIndex !is cast(int)hItem || (effect & DND.FEEDBACK_SELECT) is 0)) { TVITEM tvItem; tvItem.hItem = cast(HANDLE) dropIndex; tvItem.mask = OS.TVIF_STATE; @@ -243,14 +244,14 @@ OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); dropIndex = -1; } - if (hItem !is -1 && hItem !is dropIndex && (effect & DND.FEEDBACK_SELECT) !is 0) { + if (cast(int)hItem !is -1 && cast(int)hItem !is dropIndex && (effect & DND.FEEDBACK_SELECT) !is 0) { TVITEM tvItem; tvItem.hItem = cast(HANDLE) hItem; tvItem.mask = OS.TVIF_STATE; tvItem.stateMask = OS.TVIS_DROPHILITED; tvItem.state = OS.TVIS_DROPHILITED; OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); - dropIndex = hItem; + dropIndex = cast(int)hItem; } if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0 || (effect & DND.FEEDBACK_INSERT_AFTER) !is 0) { bool before = (effect & DND.FEEDBACK_INSERT_BEFORE) !is 0; @@ -263,7 +264,7 @@ * Since the insert mark can not be queried from the tree, * use the Tree API rather than calling the OS directly. */ - TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, hItem); + TreeItem item = cast(TreeItem)tree.getDisplay().findWidget(tree.handle, cast(int)hItem); if (item !is null) { if (item !is insertItem || before !is insertBefore) { tree.setInsertMark(item, before); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/dnd/URLTransfer.d --- a/dwt/dnd/URLTransfer.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/dnd/URLTransfer.d Sat May 17 17:34:28 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. + * Copyright (c) 2000, 20007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,8 +12,6 @@ *******************************************************************************/ module dwt.dnd.URLTransfer; -//import java.net.URL; - import dwt.internal.ole.win32.COM; import dwt.internal.ole.win32.OBJIDL; import dwt.internal.win32.OS; @@ -28,21 +26,19 @@ /** * The class URLTransfer provides a platform specific mechanism - * for converting text in URL format represented as a java String[] + * for converting text in URL format represented as a java String * to a platform specific representation of the data and vice versa. See - * Transfer for additional information. The first string in the - * array is mandatory and must contain the fully specified url. The second - * string in the array is optional and if present contains the title for the - * page. + * Transfer for additional information. The string + * must contain a fully specified url. * - *

An example of a java String[] containing a URL is shown + *

An example of a java String containing a URL is shown * below:

* *
- *     String[] urlData = new String[] {"http://www.eclipse.org", "Eclipse.org Main Page"};
+ *     String url = "http://www.eclipse.org";
  * 
*/ -/*public*/ class URLTransfer : ByteArrayTransfer { +public class URLTransfer : ByteArrayTransfer { static URLTransfer _instance; static const String CFSTR_INETURL = "UniformResourceLocator"; //$NON-NLS-1$ @@ -71,11 +67,11 @@ } /** - * This implementation of javaToNative converts a URL and optionally a title - * represented by a java String[] to a platform specific representation. + * This implementation of javaToNative converts a URL + * represented by a java String to a platform specific representation. * For additional information see Transfer#javaToNative. * - * @param object a java String[] containing a URL and optionally, a title + * @param object a java String containing a URL * @param transferData an empty TransferData object; this * object will be filled in on return with the platform specific format of the data */ @@ -85,7 +81,7 @@ } transferData.result = COM.E_FAIL; // URL is stored as a null terminated byte array - String url = (cast(ArrayWrapperString2)object).array[0]; + String url = (cast(ArrayWrapperString)object).array; int codePage = OS.GetACP(); wchar[] chars = StrToWCHARs(codePage, url, true ); int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars.ptr, -1, null, 0, null, null); @@ -106,12 +102,12 @@ /** * This implementation of nativeToJava converts a platform specific - * representation of a URL and optionally, a title to a java String[]. + * representation of a URL to a java String. * For additional information see Transfer#nativeToJava. * * @param transferData the platform specific representation of the data to be - * been converted - * @return a java String[] containing a URL and optionally a title if the + * converted + * @return a java String containing a URL if the * conversion was successful; otherwise null */ public Object nativeToJava(TransferData transferData){ @@ -134,7 +130,7 @@ if (cchWideChar is 0) return null; wchar[] lpWideCharStr = new wchar [cchWideChar - 1]; OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr.ptr, lpWideCharStr.length); - return new ArrayWrapperString2( [ WCHARzToStr( lpWideCharStr.ptr) ]); + return new ArrayWrapperString( WCHARzToStr( lpWideCharStr.ptr) ); } finally { OS.GlobalUnlock(hMem); } @@ -152,19 +148,8 @@ } bool checkURL(Object object) { - if( auto s = cast(ArrayWrapperString2)object ){ - if( s.array.length is 0 ) return false; - String[] strings = s.array; - if (strings[0] is null || strings[0].length is 0) return false; - //PORTING_FIXME: how to validata URL? - /+try { - new URL(strings[0]); - } catch (java.net.MalformedURLException e) { - return false; - }+/ - return true; - } - return false; + return object !is null && (null !is cast(ArrayWrapperString)object) && (cast(ArrayWrapperString)object).array.length > 0; + } protected bool validate(Object object) { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/Color.d --- a/dwt/graphics/Color.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/Color.d Sat May 17 17:34:28 2008 +0200 @@ -40,6 +40,8 @@ public final class Color : Resource { + alias Resource.init_ init_; + /** * the handle to the OS color resource * (Warning: This field is platform dependent) @@ -55,7 +57,8 @@ /** * Prevents uninitialized instances from being created outside the package. */ -this() { +this(Device device) { + super(device); } /** @@ -83,10 +86,9 @@ * @see #dispose */ public this (Device device, int red, int green, int blue) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, red, green, blue); - if (device.tracking) device.new_Object(this); + super(device); + init_(red, green, blue); + init_(); } /** @@ -112,22 +114,13 @@ * @see #dispose */ public this (Device device, RGB rgb) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (rgb is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, rgb.red, rgb.green, rgb.blue); - if (device.tracking) device.new_Object(this); + init_(rgb.red, rgb.green, rgb.blue); + init_(); } -/** - * Disposes of the operating system resources associated with - * the color. Applications must dispose of all colors which - * they allocate. - */ -override public void dispose() { - if (handle is -1) return; - if (device.isDisposed()) return; - +void destroy() { /* * If this is a palette-based device, * Decrease the reference count for this color. @@ -143,8 +136,6 @@ } } handle = -1; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -249,11 +240,10 @@ * * @see #dispose */ -void init_(Device device, int red, int green, int blue) { +void init_(int red, int green, int blue) { if (red > 255 || red < 0 || green > 255 || green < 0 || blue > 255 || blue < 0) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); } - this.device = device; handle = (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16); /* If this is not a palette-based device, return */ @@ -338,10 +328,8 @@ * @return a new color object containing the specified device and handle */ public static Color win32_new(Device device, int handle) { - if (device is null) device = Device.getDevice(); - Color color = new Color(); + Color color = new Color(device); color.handle = handle; - color.device = device; return color; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/Cursor.d --- a/dwt/graphics/Cursor.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/Cursor.d Sat May 17 17:34:28 2008 +0200 @@ -54,6 +54,8 @@ public final class Cursor : Resource { + alias Resource.init_ init_; + /** * the handle to the OS cursor resource * (Warning: This field is platform dependent) @@ -149,7 +151,8 @@ /** * Prevents uninitialized instances from being created outside the package. */ -this() { +this(Device device) { + super(device); } /** @@ -194,10 +197,8 @@ * @see DWT#CURSOR_HAND */ public this(Device device, int style) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; - int lpCursorName = 0; + super(device); + int /*long*/ lpCursorName = 0; switch (style) { case DWT.CURSOR_HAND: lpCursorName = OS.IDC_HAND; break; case DWT.CURSOR_ARROW: lpCursorName = OS.IDC_ARROW; break; @@ -240,7 +241,7 @@ } } if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); } /** @@ -275,9 +276,7 @@ * */ public this(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (mask is null) { if (source.getTransparencyType() !is DWT.TRANSPARENCY_MASK) { @@ -307,7 +306,7 @@ static if (OS.IsWinCE) DWT.error (DWT.ERROR_NOT_IMPLEMENTED); handle = OS.CreateCursor(hInst, hotspotX, hotspotY, source.width, source.height, sourceData.ptr, maskData.ptr); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); } /** @@ -338,9 +337,7 @@ * @since 3.0 */ public this(Device device, ImageData source, int hotspotX, int hotspotY) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); /* Check the hotspots */ if (hotspotX >= source.width || hotspotX < 0 || @@ -348,7 +345,7 @@ DWT.error(DWT.ERROR_INVALID_ARGUMENT); } ImageData mask = source.getTransparencyMask(); - int[] result = Image.init_(device, null, source, mask); + int[] result = Image.init_(this.device, null, source, mask); auto hBitmap = cast(HBITMAP)result[0]; auto hMask = cast(HBITMAP)result[1]; /* Create the icon */ @@ -363,18 +360,10 @@ OS.DeleteObject(hBitmap); OS.DeleteObject(hMask); isIcon = true; - if (device.tracking) device.new_Object(this); + init_(); } -/** - * Disposes of the operating system resources associated with - * the cursor. Applications must dispose of all cursors which - * they allocate. - */ -override public void dispose () { - if (handle is null) return; - if (device.isDisposed()) return; - +void destroy () { /* * It is an error in Windows to destroy the current * cursor. Check that the cursor that is about to @@ -402,8 +391,6 @@ static if (!OS.IsWinCE) OS.DestroyCursor(handle); } handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -477,10 +464,8 @@ * @return a new cursor object containing the specified device and handle */ public static Cursor win32_new(Device device, HCURSOR handle) { - if (device is null) device = Device.getDevice(); - Cursor cursor = new Cursor(); + Cursor cursor = new Cursor(device); cursor.handle = handle; - cursor.device = device; return cursor; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/Device.d --- a/dwt/graphics/Device.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/Device.d Sat May 17 17:34:28 2008 +0200 @@ -17,6 +17,14 @@ import dwt.internal.gdip.Gdip; import dwt.internal.win32.OS; +import dwt.graphics.Cursor; +import dwt.graphics.GC; +import dwt.graphics.Image; +import dwt.graphics.Path; +import dwt.graphics.Pattern; +import dwt.graphics.Region; +import dwt.graphics.TextLayout; +import dwt.graphics.Transform; import dwt.graphics.Drawable; import dwt.graphics.DeviceData; import dwt.graphics.Rectangle; @@ -27,8 +35,11 @@ import dwt.dwthelper.Runnable; import dwt.dwthelper.System; + import dwt.dwthelper.utils; import tango.core.Exception; +import tango.util.Convert; +import tango.io.Stdout; /** * This class is the abstract superclass of all device objects, @@ -49,6 +60,7 @@ bool tracking; Exception [] errors; Object [] objects; + Object trackingLock; /** * Palette @@ -64,7 +76,7 @@ int [] colorRefCount; /* System Font */ - HFONT systemFont; + Font systemFont; /* Font Enumeration */ int nFonts = 256; @@ -74,6 +86,7 @@ /* Scripts */ SCRIPT_PROPERTIES*[] scripts; + LOGFONT* [] logFontsCache; /* Advanced Graphics */ ULONG_PTR gdipToken; @@ -134,22 +147,20 @@ * @see DeviceData */ public this(DeviceData data) { - synchronized (this.classinfo) { + synchronized (Device.classinfo) { debug_ = DEBUG; tracking = DEBUG; if (data !is null) { debug_ = data.debug_; tracking = data.tracking; } - create (data); - init_ (); if (tracking) { errors = new Exception [128]; objects = new Object [128]; + trackingLock = new Object (); } - - /* Initialize the system font slot */ - systemFont = getSystemFont().handle; + create (data); + init_ (); gdipToken = 0; } } @@ -179,8 +190,8 @@ void checkGDIP() { if (gdipToken) return; - static if (OS.IsWinCE) DWT.error(DWT.ERROR_NOT_IMPLEMENTED); - int oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS); + int oldErrorMode = 0; + static if (!OS.IsWinCE) oldErrorMode = OS.SetErrorMode (OS.SEM_FAILCRITICALERRORS); try { ULONG_PTR token; GdiplusStartupInput input; @@ -191,7 +202,7 @@ } catch (Exception t) { DWT.error (DWT.ERROR_NO_GRAPHICS_LIBRARY, t, " [GDI+ is required]"); //$NON-NLS-1$ } finally { - OS.SetErrorMode (oldErrorMode); + if (!OS.IsWinCE) OS.SetErrorMode (oldErrorMode); } } @@ -272,23 +283,31 @@ * @see #checkDevice */ public void dispose () { - if (isDisposed()) return; - checkDevice (); - release (); - destroy (); - disposed = true; - if (tracking) { - objects = null; - errors = null; + synchronized (Device.classinfo) { + if (isDisposed()) return; + checkDevice (); + release (); + destroy (); + disposed = true; + if (tracking) { + synchronized (trackingLock) { + printErrors (); + objects = null; + errors = null; + trackingLock = null; + } + } } } void dispose_Object (Object object) { - for (int i=0; itrue when the device is disposed and false otherwise */ public bool isDisposed () { - return disposed; + synchronized (Device.classinfo) { + return disposed; + } } /** @@ -802,21 +832,71 @@ } void new_Object (Object object) { - for (int i=0; i */ public this(Device device, FontData fd) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, fd); - if (device.tracking) device.new_Object(this); + super(device); + init_(fd); + init_(); } /** @@ -109,15 +110,14 @@ * @since 2.1 */ public this(Device device, FontData[] fds) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (fds is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (fds.length is 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); for (int i=0; i */ public this(Device device, String name, int height, int style) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (name is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, new FontData (name, height, style)); - if (device.tracking) device.new_Object(this); + init_(new FontData (name, height, style)); + init_(); } /*public*/ this(Device device, String name, float height, int style) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (name is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, new FontData (name, height, style)); - if (device.tracking) device.new_Object(this); + init_(new FontData (name, height, style)); + init_(); } - -/** - * Disposes of the operating system resources associated with - * the font. Applications must dispose of all fonts which - * they allocate. - */ -override public void dispose() { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy() { OS.DeleteObject(handle); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -223,9 +211,8 @@ return cast(hash_t)handle; } -void init_ (Device device, FontData fd) { +void init_ (FontData fd) { if (fd is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; LOGFONT* logFont = &fd.data; int lfHeight = logFont.lfHeight; logFont.lfHeight = device.computePixels(fd.height); @@ -274,10 +261,8 @@ * @return a new font object containing the specified device and handle */ public static Font win32_new(Device device, HFONT handle) { - if (device is null) device = Device.getDevice(); - Font font = new Font(); + Font font = new Font(device); font.handle = handle; - font.device = device; return font; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/GC.d --- a/dwt/graphics/GC.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/GC.d Sat May 17 17:34:28 2008 +0200 @@ -73,6 +73,8 @@ public final class GC : Resource { + alias Resource.init_ init_; + /** * the handle to the OS device context * (Warning: This field is platform dependent) @@ -181,7 +183,7 @@ if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); this.device = data.device = device; init_ (drawable, data, hDC); - if (device.tracking) device.new_Object(this); + init_(); } static int checkStyle(int style) { @@ -263,7 +265,7 @@ default: } if (dashes !is null) { - Gdip.Pen_SetDashPattern(pen, dashes, dashes.length); + Gdip.Pen_SetDashPattern(pen, dashes.ptr, dashes.length); Gdip.Pen_SetDashStyle(pen, Gdip.DashStyleCustom); Gdip.Pen_SetDashOffset(pen, dashOffset); } else { @@ -323,25 +325,26 @@ } } if ((state & FONT) !is 0) { - OS.SelectObject(handle, data.hFont); - auto font = createGdipFont(handle, data.hFont); + Font font = data.font; + OS.SelectObject(handle, font.handle); + auto gdipFont = createGdipFont(handle, font.handle); if (data.gdipFont !is null) Gdip.Font_delete(data.gdipFont); - data.gdipFont = font; + data.gdipFont = gdipFont; } if ((state & DRAW_OFFSET) !is 0) { data.gdipXOffset = data.gdipYOffset = 0; auto matrix = Gdip.Matrix_new(1, 0, 0, 1, 0, 0); - float[6] elements; + float[2] point; point[0]=1.0; point[1]=1.0; Gdip.Graphics_GetTransform(gdipGraphics, matrix); - Gdip.Matrix_GetElements(matrix, elements ); + Gdip.Matrix_TransformPoints(matrix, cast(Gdip.PointF*)point.ptr, 1); Gdip.Matrix_delete(matrix); - float scaling = elements[0]; + float scaling = point[0]; if (scaling < 0) scaling = -scaling; float penWidth = data.lineWidth * scaling; if (penWidth is 0 || (cast(int)penWidth % 2) is 1) { data.gdipXOffset = 0.5f / scaling; } - scaling = elements[3]; + scaling = point[1]; if (scaling < 0) scaling = -scaling; penWidth = data.lineWidth * scaling; if (penWidth is 0 || (cast(int)penWidth % 2) is 1) { @@ -439,7 +442,8 @@ OS.SetTextColor(handle, data.foreground); } if ((state & FONT) !is 0) { - OS.SelectObject(handle, data.hFont); + Font font = data.font; + OS.SelectObject(handle, font.handle); } } @@ -627,11 +631,12 @@ *
  • ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable
  • * */ -override public void dispose() { - if (handle is null) return; - if (data.device.isDisposed()) return; - +void destroy() { + bool gdip = data.gdipGraphics !is null; disposeGdip(); + if (gdip && (data.style & DWT.MIRRORED) !is 0) { + OS.SetLayout(handle, OS.GetLayout(handle) | OS.LAYOUT_RTL); + } /* Select stock pen and brush objects and free resources */ if (data.hPen !is null) { @@ -661,14 +666,11 @@ /* * Dispose the HDC. */ - Device device = data.device; if (drawable !is null) drawable.internal_dispose_GC(handle, data); drawable = null; handle = null; data.image = null; data.ps = null; - if (device.tracking) device.dispose_Object(this); - data.device = null; data = null; } @@ -816,6 +818,7 @@ public void drawFocus (int x, int y, int width, int height) { if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); if ((data.uiState & OS.UISF_HIDEFOCUS) !is 0) return; + data.focusDrawn = true; HDC hdc = handle; int state = 0; auto gdipGraphics = data.gdipGraphics; @@ -837,13 +840,11 @@ Gdip.Graphics_GetTransform(gdipGraphics, matrix); if (!Gdip.Matrix_IsIdentity(matrix)) { gotElements = true; - Gdip.Matrix_GetElements(matrix, lpXform); + Gdip.Matrix_GetElements(matrix, lpXform.ptr); } Gdip.Matrix_delete(matrix); hdc = Gdip.Graphics_GetHDC(gdipGraphics); state = OS.SaveDC(hdc); - OS.SetBkColor(hdc, data.background); - OS.SetTextColor(hdc, data.foreground); if (gotElements) { OS.SetGraphicsMode(hdc, OS.GM_ADVANCED); OS.SetWorldTransform(hdc, cast(XFORM*)lpXform.ptr); @@ -853,12 +854,16 @@ OS.DeleteObject(clipRgn); } } + OS.SetBkColor(hdc, 0xFFFFFF); + OS.SetTextColor(hdc, 0x000000); RECT rect; OS.SetRect(&rect, x, y, x + width, y + height); OS.DrawFocusRect(hdc, &rect); if (gdipGraphics !is null) { OS.RestoreDC(hdc, state); Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc); + } else { + data.state &= ~(BACKGROUND_TEXT | FOREGROUND_TEXT); } } @@ -934,7 +939,7 @@ void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple) { if (data.gdipGraphics !is null) { //TODO - cache bitmap - int[] gdipImage = srcImage.createGdipImage(); + int /*long*/ [] gdipImage = srcImage.createGdipImage(); auto img = cast(Gdip.Image) gdipImage[0]; int imgWidth = Gdip.Image_GetWidth(img); int imgHeight = Gdip.Image_GetHeight(img); @@ -1426,7 +1431,8 @@ } auto srcHdc = OS.CreateCompatibleDC(handle); auto oldSrcBitmap = OS.SelectObject(srcHdc, srcColor); - auto destHdc = handle, x = destX, y = destY; + auto destHdc = handle; + int x = destX, y = destY; HDC tempHdc; HBITMAP tempBitmap; HBITMAP oldTempBitmap; @@ -1806,7 +1812,7 @@ auto gdipGraphics = data.gdipGraphics; if (gdipGraphics !is null) { Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend); - Gdip.Graphics_DrawPolygon(gdipGraphics, data.gdipPen, cast(Gdip.Point[])pointArray, pointArray.length/2); + Gdip.Graphics_DrawPolygon(gdipGraphics, data.gdipPen, cast(Gdip.Point*)pointArray.ptr, pointArray.length/2); Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend); return; } @@ -1851,7 +1857,7 @@ auto gdipGraphics = data.gdipGraphics; if (gdipGraphics !is null) { Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend); - Gdip.Graphics_DrawLines(gdipGraphics, data.gdipPen, cast(Gdip.Point[])pointArray, pointArray.length / 2); + Gdip.Graphics_DrawLines(gdipGraphics, data.gdipPen, cast(Gdip.Point*)pointArray.ptr, pointArray.length / 2); Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend); return; } @@ -1898,6 +1904,14 @@ checkGC(DRAW); auto gdipGraphics = data.gdipGraphics; if (gdipGraphics !is null) { + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend); Gdip.Graphics_DrawRectangle(gdipGraphics, data.gdipPen, x, y, width, height); Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend); @@ -2036,29 +2050,33 @@ nah = 0 - nah; Gdip.Graphics_TranslateTransform(gdipGraphics, data.gdipXOffset, data.gdipYOffset, Gdip.MatrixOrderPrepend); - auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate); - if (path is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (nw > naw) { - if (nh > nah) { - Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nah, 0, -90); - Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nah, -90, -90); - Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, naw, nah, -180, -90); - Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90); + if (naw is 0 || nah is 0) { + Gdip.Graphics_DrawRectangle(gdipGraphics, data.gdipPen, x, y, width, height); + } else { + auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate); + if (path is null) DWT.error(DWT.ERROR_NO_HANDLES); + if (nw > naw) { + if (nh > nah) { + Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nah, 0, -90); + Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nah, -90, -90); + Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, naw, nah, -180, -90); + Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90); + } else { + Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nh, -270, -180); + Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nh, -90, -180); + } } else { - Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nh, -270, -180); - Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nh, -90, -180); + if (nh > nah) { + Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nah, 0, -180); + Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, nw, nah, -180, -180); + } else { + Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nh, 0, 360); + } } - } else { - if (nh > nah) { - Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nah, 0, -180); - Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, nw, nah, -180, -180); - } else { - Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nh, 0, 360); - } + Gdip.GraphicsPath_CloseFigure(path); + Gdip.Graphics_DrawPath(gdipGraphics, pen, path); + Gdip.GraphicsPath_delete(path); } - Gdip.GraphicsPath_CloseFigure(path); - Gdip.Graphics_DrawPath(gdipGraphics, pen, path); - Gdip.GraphicsPath_delete(path); Gdip.Graphics_TranslateTransform(gdipGraphics, -data.gdipXOffset, -data.gdipYOffset, Gdip.MatrixOrderPrepend); } @@ -2316,7 +2334,7 @@ if ((data.style & DWT.MIRRORED) !is 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft; Gdip.StringFormat_SetFormatFlags(format, formatFlags); float[] tabs = (flags & DWT.DRAW_TAB) !is 0 ? [ cast(float) measureSpace(data.gdipFont, format) * 8] : new float[1]; - Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs); + Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs.ptr); int hotkeyPrefix = (flags & DWT.DRAW_MNEMONIC) !is 0 ? Gdip.HotkeyPrefixShow : Gdip.HotkeyPrefixNone; if ((flags & DWT.DRAW_MNEMONIC) !is 0 && (data.uiState & OS.UISF_HIDEACCEL) !is 0) hotkeyPrefix = Gdip.HotkeyPrefixHide; Gdip.StringFormat_SetHotkeyPrefix(format, hotkeyPrefix); @@ -2768,7 +2786,7 @@ checkGC(FILL); if (data.gdipGraphics !is null) { int mode = OS.GetPolyFillMode(handle) is OS.WINDING ? Gdip.FillModeWinding : Gdip.FillModeAlternate; - Gdip.Graphics_FillPolygon(data.gdipGraphics, data.gdipBrush, cast(Gdip.Point[])pointArray, pointArray.length / 2, mode); + Gdip.Graphics_FillPolygon(data.gdipGraphics, data.gdipBrush, cast(Gdip.Point*)pointArray.ptr, pointArray.length / 2, mode); return; } if ((data.style & DWT.MIRRORED) !is 0) { @@ -2803,6 +2821,14 @@ if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); checkGC(FILL); if (data.gdipGraphics !is null) { + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } Gdip.Graphics_FillRectangle(data.gdipGraphics, data.gdipBrush, x, y, width, height); return; } @@ -2886,29 +2912,33 @@ if (nah < 0) nah = 0 - nah; - auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate); - if (path is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (nw > naw) { - if (nh > nah) { - Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nah, 0, -90); - Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nah, -90, -90); - Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, naw, nah, -180, -90); - Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90); + if (naw is 0 || nah is 0) { + Gdip.Graphics_FillRectangle(data.gdipGraphics, data.gdipBrush, x, y, width, height); + } else { + auto path = Gdip.GraphicsPath_new(Gdip.FillModeAlternate); + if (path is null) DWT.error(DWT.ERROR_NO_HANDLES); + if (nw > naw) { + if (nh > nah) { + Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nah, 0, -90); + Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nah, -90, -90); + Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, naw, nah, -180, -90); + Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny + nh - nah, naw, nah, -270, -90); + } else { + Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nh, -270, -180); + Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nh, -90, -180); + } } else { - Gdip.GraphicsPath_AddArc(path, nx + nw - naw, ny, naw, nh, -270, -180); - Gdip.GraphicsPath_AddArc(path, nx, ny, naw, nh, -90, -180); + if (nh > nah) { + Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nah, 0, -180); + Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, nw, nah, -180, -180); + } else { + Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nh, 0, 360); + } } - } else { - if (nh > nah) { - Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nah, 0, -180); - Gdip.GraphicsPath_AddArc(path, nx, ny + nh - nah, nw, nah, -180, -180); - } else { - Gdip.GraphicsPath_AddArc(path, nx, ny, nw, nh, 0, 360); - } + Gdip.GraphicsPath_CloseFigure(path); + Gdip.Graphics_FillPath(gdipGraphics, brush, path); + Gdip.GraphicsPath_delete(path); } - Gdip.GraphicsPath_CloseFigure(path); - Gdip.Graphics_FillPath(gdipGraphics, brush, path); - Gdip.GraphicsPath_delete(path); } void flush () { @@ -3269,7 +3299,7 @@ */ public Font getFont () { if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); - return Font.win32_new(data.device, data.hFont); + return data.font; } /** @@ -3666,15 +3696,34 @@ Gdip.Matrix identity() { if ((data.style & DWT.MIRRORED) !is 0) { int width = 0; - Image image = data.image; - if (image !is null) { + int technology = OS.GetDeviceCaps(handle, OS.TECHNOLOGY); + if (technology is OS.DT_RASPRINTER) { + width = OS.GetDeviceCaps(handle, OS.PHYSICALWIDTH); + } else { + Image image = data.image; + if (image !is null) { BITMAP bm; OS.GetObject(image.handle, BITMAP.sizeof, &bm); - width = bm.bmWidth; - } else if (data.hwnd !is null) { - RECT rect; - OS.GetClientRect(data.hwnd, &rect); - width = rect.right - rect.left; + width = bm.bmWidth; + } else { + HWND hwnd; + static if( OS.IsWinCE ){ + hwnd = data.hwnd; + } + else{ + hwnd = OS.WindowFromDC(handle); + } + if (hwnd !is null) { + RECT rect; + OS.GetClientRect(hwnd, &rect); + width = rect.right - rect.left; + } else { + auto hBitmap = OS.GetCurrentObject(handle, OS.OBJ_BITMAP); + BITMAP bm; + OS.GetObject(hBitmap, BITMAP.sizeof, &bm); + width = bm.bmWidth; + } + } } POINT pt; static if (!OS.IsWinCE) OS.GetWindowOrgEx (handle, &pt); @@ -3697,11 +3746,11 @@ data.background = OS.GetBkColor(hDC); } data.state &= ~(NULL_BRUSH | NULL_PEN); - auto hFont = data.hFont; - if (hFont !is null && hFont !is cast(HFONT)-1 ) { + Font font = data.font; + if (font !is null) { data.state &= ~FONT; } else { - data.hFont = OS.GetCurrentObject(hDC, OS.OBJ_FONT); + data.font = Font.win32_new(device, OS.GetCurrentObject(hDC, OS.OBJ_FONT)); } auto hPalette = data.device.hPalette; if (hPalette !is null) { @@ -3763,8 +3812,16 @@ */ public bool isClipped() { if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + auto gdipGraphics = data.gdipGraphics; + if (gdipGraphics !is null) { + auto rgn = Gdip.Region_new(); + Gdip.Graphics_GetClip(data.gdipGraphics, rgn); + bool isInfinite = Gdip.Region_IsInfinite(rgn, gdipGraphics) !is 0; + Gdip.Region_delete(rgn); + return !isInfinite; + } auto region = OS.CreateRectRgn(0, 0, 0, 0); - auto result = OS.GetClipRgn(handle, region); + int result = OS.GetClipRgn(handle, region); OS.DeleteObject(region); return result > 0; } @@ -4068,7 +4125,7 @@ initGdip(); int mode = OS.GetPolyFillMode(handle) is OS.WINDING ? Gdip.FillModeWinding : Gdip.FillModeAlternate; Gdip.GraphicsPath_SetFillMode(path.handle, mode); - Gdip.Graphics_SetClip(data.gdipGraphics, path.handle); + Gdip.Graphics_SetClipPath(data.gdipGraphics, path.handle); } } @@ -4163,7 +4220,7 @@ public void setFont (Font font) { if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); if (font !is null && font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - data.hFont = font !is null ? font.handle : data.device.systemFont; + data.font = font !is null ? font : data.device.systemFont; data.state &= ~FONT; } @@ -4327,7 +4384,7 @@ DWT.error(DWT.ERROR_INVALID_ARGUMENT); } } - int cap = attributes.join; + int cap = attributes.cap; if (cap !is data.lineCap) { mask |= LINE_CAP; switch (cap) { @@ -4800,7 +4857,7 @@ if ((data.style & DWT.MIRRORED) !is 0) formatFlags |= Gdip.StringFormatFlagsDirectionRightToLeft; Gdip.StringFormat_SetFormatFlags(format, formatFlags); float[] tabs = (flags & DWT.DRAW_TAB) !is 0 ? [measureSpace(data.gdipFont, format) * 8] : new float[1]; - Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs); + Gdip.StringFormat_SetTabStops(format, 0, tabs.length, tabs.ptr); Gdip.StringFormat_SetHotkeyPrefix(format, (flags & DWT.DRAW_MNEMONIC) !is 0 ? Gdip.HotkeyPrefixShow : Gdip.HotkeyPrefixNone); Gdip.Graphics_MeasureString(data.gdipGraphics, buffer, length_, data.gdipFont, pt, format, bounds); Gdip.StringFormat_delete(format); @@ -4876,6 +4933,13 @@ public static GC win32_new(HDC hDC, GCData data) { GC gc = new GC(); gc.device = data.device; + data.style |= DWT.LEFT_TO_RIGHT; + if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) { + int flags = OS.GetLayout (hDC); + if ((flags & OS.LAYOUT_RTL) !is 0) { + data.style |= DWT.RIGHT_TO_LEFT | DWT.MIRRORED; + } + } gc.init_(null, data, hDC); return gc; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/GCData.d --- a/dwt/graphics/GCData.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/GCData.d Sat May 17 17:34:28 2008 +0200 @@ -19,6 +19,7 @@ import dwt.graphics.Image; import dwt.graphics.Device; import dwt.graphics.Pattern; +import dwt.graphics.Font; /** * Instances of this class are descriptions of GCs in terms @@ -36,7 +37,7 @@ public int style, state = -1; public int foreground = -1; public int background = -1; - public HFONT hFont; + public Font font; public Pattern foregroundPattern; public Pattern backgroundPattern; public int lineStyle = DWT.LINE_SOLID; @@ -47,7 +48,6 @@ public float[] lineDashes; public float lineMiterLimit = 10; public int alpha = 0xFF; - public int uiState = 0; public Image image; public HPEN hPen, hOldPen; @@ -63,5 +63,7 @@ public Gdip.SolidBrush gdipBgBrush; public Gdip.Font gdipFont; public float gdipXOffset, gdipYOffset; + public int uiState = 0; + public bool focusDrawn; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/Image.d --- a/dwt/graphics/Image.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/Image.d Sat May 17 17:34:28 2008 +0200 @@ -88,6 +88,8 @@ public final class Image : Resource, Drawable { + alias Resource.init_ init_; + /** * specifies whether the receiver is a bitmap or an icon * (one of DWT.BITMAP, DWT.ICON) @@ -156,7 +158,8 @@ /** * Prevents uninitialized instances from being created outside the package. */ -this () { +this (Device device) { + super(device); } /** @@ -190,10 +193,9 @@ * */ public this(Device device, int width, int height) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, width, height); - if (device.tracking) device.new_Object(this); + super(device); + init_(width, height); + init_(); } /** @@ -228,15 +230,14 @@ * */ public this(Device device, Image srcImage, int flag) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); + device = this.device; if (srcImage is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (srcImage.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); Rectangle rect = srcImage.getBounds(); + this.type = srcImage.type; switch (flag) { case DWT.IMAGE_COPY: { - this.type = srcImage.type; switch (type) { case DWT.BITMAP: /* Get the HDC for the device */ @@ -269,7 +270,7 @@ break; case DWT.ICON: static if (OS.IsWinCE) { - init_(device, srcImage.data); + init_(srcImage.data); } else { handle = OS.CopyImage(srcImage.handle, OS.IMAGE_ICON, rect.width, rect.height, 0); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); @@ -278,8 +279,7 @@ default: DWT.error(DWT.ERROR_INVALID_IMAGE); } - if (device.tracking) device.new_Object(this); - return; + break; } case DWT.IMAGE_DISABLE: { ImageData data = srcImage.getImageData(); @@ -337,9 +337,8 @@ offset++; } } - init_ (device, newData); - if (device.tracking) device.new_Object(this); - return; + init_ (newData); + break; } case DWT.IMAGE_GRAY: { ImageData data = srcImage.getImageData(); @@ -402,13 +401,13 @@ } } } - init_ (device, newData); - if (device.tracking) device.new_Object(this); - return; + init_ (newData); + break; } default: DWT.error(DWT.ERROR_INVALID_ARGUMENT); } + init_(); } /** @@ -442,11 +441,10 @@ * */ public this(Device device, Rectangle bounds) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (bounds is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, bounds.width, bounds.height); - if (device.tracking) device.new_Object(this); + init_(bounds.width, bounds.height); + init_(); } /** @@ -468,10 +466,9 @@ * */ public this(Device device, ImageData data) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, data); - if (device.tracking) device.new_Object(this); + super(device); + init_(data); + init_(); } /** @@ -500,16 +497,15 @@ * */ public this(Device device, ImageData source, ImageData mask) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (mask is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (source.width !is mask.width || source.height !is mask.height) { DWT.error(DWT.ERROR_INVALID_ARGUMENT); } mask = ImageData.convertMask(mask); - init_(device, this, source, mask); - if (device.tracking) device.new_Object(this); + init_(this.device, this, source, mask); + init_(); } /** @@ -561,10 +557,9 @@ * */ public this (Device device, InputStream stream) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - init_(device, new ImageData(stream)); - if (device.tracking) device.new_Object(this); + super(device); + init_(new ImageData(stream)); + init_(); } /** @@ -595,12 +590,22 @@ * */ public this (Device device, String filename) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); + device = this.device; if (filename is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + bool gdip = true; try { device.checkGDIP(); + } catch (DWTException e) { + gdip = false; + } + /* + * Bug in GDI+. For some reason, Bitmap.LockBits() segment faults + * when loading GIF files in 64-bit Windows. The fix is to not use + * GDI+ image loading in this case. + */ + if (gdip && (void*).sizeof is 8 && filename.toLowerCase().endsWith(".gif")) gdip = false; + if (gdip) { int length = filename.length; char[] chars = new char[length+1]; filename.getChars(0, length, chars, 0); @@ -741,7 +746,7 @@ ImageData img = new ImageData(width, height, depth, paletteData, scanlinePad, data); img.transparentPixel = transparentPixel; img.alphaData = alphaData; - init_(device, img); + init_(img); } } } @@ -753,9 +758,9 @@ return; } } - } catch (DWTException e) {} - init_(device, new ImageData(filename)); - if(device.tracking) device.new_Object(this); + } + init_(new ImageData(filename)); + init_(); } /** @@ -853,7 +858,7 @@ offset += 4; } } - int pBits; + void* pBits; HBITMAP hDib = OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0); if (hDib is null) DWT.error(DWT.ERROR_NO_HANDLES); @@ -877,7 +882,7 @@ // active, even though it might be unlikely given the short span of time that the // function has them stored in the int array. -int[] createGdipImage() { +int /*long*/ [] createGdipImage() { switch (type) { case DWT.BITMAP: { if (alpha !is -1 || alphaData !is null || transparentPixel !is -1) { @@ -996,7 +1001,14 @@ int imgHeight = hBitmap is iconInfo.hbmMask ? bm.bmHeight / 2 : bm.bmHeight; Gdip.Bitmap img; ubyte* pixels; - if (imgWidth > imgHeight) { + /* + * Bug in GDI+. Bitmap_new() segments fault if the image width + * is greater than the image height. + * + * Note that it also fails to generated an appropriate alpha + * channel when the icon depth is 32. + */ + if (imgWidth > imgHeight || bm.bmBitsPixel is 32) { auto hDC = device.internal_new_GC(null); auto srcHdc = OS.CreateCompatibleDC(hDC); auto oldSrcBitmap = OS.SelectObject(srcHdc, hBitmap); @@ -1013,12 +1025,14 @@ OS.MoveMemory(srcData.ptr, dibBM.bmBits, srcData.length); OS.DeleteObject(memDib); OS.SelectObject(srcHdc, iconInfo.hbmMask); - for (int y = 0, dp = 0; y < imgHeight; ++y) { + for (int y = 0, dp = 3; y < imgHeight; ++y) { for (int x = 0; x < imgWidth; ++x) { - if (OS.GetPixel(srcHdc, x, y) !is 0) { - srcData[dp + 3] = cast(ubyte)0; - } else { - srcData[dp + 3] = cast(ubyte)0xFF; + if (srcData[dp] is 0) { + if (OS.GetPixel(srcHdc, x, y) !is 0) { + srcData[dp] = cast(ubyte)0; + } else { + srcData[dp] = cast(ubyte)0xFF; + } } dp += 4; } @@ -1043,14 +1057,7 @@ return null; } -/** - * Disposes of the operating system resources associated with - * the image. Applications must dispose of all images which - * they allocate. - */ -override public void dispose () { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy () { if (memGC !is null) memGC.dispose(); if (type is DWT.ICON) { static if (OS.IsWinCE) data = null; @@ -1060,8 +1067,6 @@ } handle = null; memGC = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -1579,11 +1584,10 @@ return cast(hash_t)handle; } -void init_(Device device, int width, int height) { +void init_(int width, int height) { if (width <= 0 || height <= 0) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } - this.device = device; type = DWT.BITMAP; auto hDC = device.internal_new_GC(null); handle = OS.CreateCompatibleBitmap(hDC, width, height); @@ -1644,8 +1648,8 @@ bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 0); } - int[1] pBits; - return OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0); + void* pBits; + return OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0); } /** @@ -1666,7 +1670,6 @@ } static int[] init_(Device device, Image image, ImageData i) { - if (image !is null) image.device = device; /* * BUG in Windows 98: @@ -1833,7 +1836,7 @@ } OS.MoveMemory(pBits, data.ptr, data.length); - int[] result = null; + int /*long*/ [] result = null; if (i.getTransparencyType() is DWT.TRANSPARENCY_MASK) { /* Get the HDC for the device */ auto hDC = device.internal_new_GC(null); @@ -1969,7 +1972,7 @@ imageData.maskData = mask.data; return init_(device, image, imageData); } -void init_(Device device, ImageData i) { +void init_(ImageData i) { if (i is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); init_(device, this, i); } @@ -2013,7 +2016,7 @@ } data.device = device; data.image = this; - data.hFont = device.systemFont; + data.font = device.systemFont; } return imageDC; } @@ -2144,11 +2147,9 @@ * @return a new image object containing the specified device, type and handle */ public static Image win32_new(Device device, int type, HGDIOBJ handle) { - if (device is null) device = Device.getDevice(); - Image image = new Image(); + Image image = new Image(device); image.type = type; image.handle = handle; - image.device = device; return image; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/ImageData.d --- a/dwt/graphics/ImageData.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/ImageData.d Sat May 17 17:34:28 2008 +0200 @@ -290,7 +290,7 @@ * * @exception IllegalArgumentException
      *
    • ERROR_INVALID_ARGUMENT - if the width or height is negative, or if the depth is not - * one of 1, 2, 4, 8, 16, 24 or 32
    • + * one of 1, 2, 4, 8, 16, 24 or 32, or the data array is too small to contain the image data *
    • ERROR_NULL_ARGUMENT - if the palette or data is null
    • *
    • ERROR_CANNOT_BE_ZERO - if the scanlinePad is zero
    • *
    @@ -445,6 +445,17 @@ int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1)) / scanlinePad * scanlinePad; + + /* + * When the image is being loaded from a PNG, we need to use the theoretical minimum + * number of bytes per line to check whether there is enough data, because the actual + * number of bytes per line is calculated based on the given depth, which may be larger + * than the actual depth of the PNG. + */ + int minBytesPerLine = type is DWT.IMAGE_PNG ? ((((width + 7) / 8) + 3) / 4) * 4 : bytesPerLine; + if (data !is null && data.length < minBytesPerLine * height) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } setAllFields( width, height, diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/Path.d --- a/dwt/graphics/Path.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/Path.d Sat May 17 17:34:28 2008 +0200 @@ -50,6 +50,8 @@ */ public class Path : Resource { + alias Resource.init_ init_; + /** * the OS resource for the Path * (Warning: This field is platform dependent) @@ -87,13 +89,84 @@ * @see #dispose() */ public this (Device device) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; - device.checkGDIP(); + super(device); + this.device.checkGDIP(); handle = Gdip.GraphicsPath_new(Gdip.FillModeAlternate); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); +} + +/** + * Constructs a new Path that is a copy of path. If + * flatness is less than or equal to zero, an unflatten + * copy of the path is created. Otherwise, it specifies the maximum + * error between the path and its flatten copy. Smaller numbers give + * better approximation. + *

    + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *

    + * + * @param device the device on which to allocate the path + * @param path the path to make a copy + * @param flatness the flatness value + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the path is null
    • + *
    • ERROR_INVALID_ARGUMENT - if the path has been disposed
    • + *
    + * @exception DWTException
      + *
    • ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available
    • + *
    + * @exception DWTError
      + *
    • ERROR_NO_HANDLES if a handle for the path could not be obtained
    • + *
    + * + * @see #dispose() + * @since 3.4 + */ +public this (Device device, Path path, float flatness) { + super(device); + if (path is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + if (path.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); + flatness = Math.max(0, flatness); + handle = Gdip.GraphicsPath_Clone(path.handle); + if (flatness !is 0) Gdip.GraphicsPath_Flatten(handle, null, flatness); + if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); + init_(); +} + +/** + * Constructs a new with the specifed PathData. + *

    + * This operation requires the operating system's advanced + * graphics subsystem which may not be available on some + * platforms. + *

    + * + * @param device the device on which to allocate the path + * @param data the data for the path + * + * @exception IllegalArgumentException
      + *
    • ERROR_NULL_ARGUMENT - if the device is null and there is no current device
    • + *
    • ERROR_NULL_ARGUMENT - if the data is null
    • + *
    + * @exception DWTException
      + *
    • ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available
    • + *
    + * @exception DWTError
      + *
    • ERROR_NO_HANDLES if a handle for the path could not be obtained
    • + *
    + * + * @see #dispose() + * @since 3.4 + */ +public this (Device device, PathData data) { + this(device); + if (data is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + init_(data); } /** @@ -321,18 +394,9 @@ Gdip.GraphicsPath_GetLastPoint(handle, currentPoint); } -/** - * Disposes of the operating system resources associated with - * the Path. Applications must dispose of all Paths that - * they allocate. - */ -override public void dispose() { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy() { Gdip.GraphicsPath_delete(handle); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -400,8 +464,8 @@ int count = Gdip.GraphicsPath_GetPointCount(handle); byte[] gdipTypes = new byte[count]; float[] points = new float[count * 2]; - Gdip.GraphicsPath_GetPathTypes(handle, gdipTypes, count); - Gdip.GraphicsPath_GetPathPoints(handle, cast(Gdip.PointF[])points, count); + Gdip.GraphicsPath_GetPathTypes(handle, gdipTypes.ptr, count); + Gdip.GraphicsPath_GetPathPoints(handle, cast(Gdip.PointF*)points.ptr, count); byte[] types = new byte[count * 2]; int index = 0, typesIndex = 0; while (index < count) { @@ -458,6 +522,33 @@ Gdip.GraphicsPath_GetLastPoint(handle, currentPoint); } +void init_(PathData data) { + byte[] types = data.types; + float[] points = data.points; + for (int i = 0, j = 0; i < types.length; i++) { + switch (types[i]) { + case DWT.PATH_MOVE_TO: + moveTo(points[j++], points[j++]); + break; + case DWT.PATH_LINE_TO: + lineTo(points[j++], points[j++]); + break; + case DWT.PATH_CUBIC_TO: + cubicTo(points[j++], points[j++], points[j++], points[j++], points[j++], points[j++]); + break; + case DWT.PATH_QUAD_TO: + quadTo(points[j++], points[j++], points[j++], points[j++]); + break; + case DWT.PATH_CLOSE: + close(); + break; + default: + dispose(); + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + } +} + /** * Returns true if the Path has been disposed, * and false otherwise. diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/Pattern.d --- a/dwt/graphics/Pattern.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/Pattern.d Sat May 17 17:34:28 2008 +0200 @@ -43,7 +43,7 @@ * @since 3.1 */ public class Pattern : Resource { - + alias Resource.init_ init_; /** * the OS resource for the Pattern * (Warning: This field is platform dependent) @@ -82,14 +82,12 @@ * @see #dispose() */ public this(Device device, Image image) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (image is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (image.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - this.device = device; - device.checkGDIP(); - int[] gdipImage = image.createGdipImage(); - auto img = cast(Gdip.Image)gdipImage[0]; + this.device.checkGDIP(); + int /*long*/[] gdipImage = image.createGdipImage(); + auto img = cast(Gdip.Image) gdipImage[0]; int width = Gdip.Image_GetWidth(img); int height = Gdip.Image_GetHeight(img); handle = cast(Gdip.Brush)Gdip.TextureBrush_new(img, Gdip.WrapModeTile, 0, 0, width, height); @@ -99,7 +97,7 @@ OS.HeapFree(hHeap, 0, cast(void*)gdipImage[1]); } if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); } /** @@ -175,14 +173,12 @@ * @since 3.2 */ public this(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + super(device); if (color1 is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (color1.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); if (color2 is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (color2.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - this.device = device; - device.checkGDIP(); + this.device.checkGDIP(); auto colorRef1 = color1.handle; int rgb = ((colorRef1 >> 16) & 0xFF) | (colorRef1 & 0xFF00) | ((colorRef1 & 0xFF) << 16); auto foreColor = Gdip.Color_new((alpha1 & 0xFF) << 24 | rgb); @@ -215,23 +211,16 @@ f[0] = 0; f[1] = 0.5f; f[2] = 1; - Gdip.LinearGradientBrush_SetInterpolationColors( cast(Gdip.LinearGradientBrush)handle, c, f, 3); + Gdip.LinearGradientBrush_SetInterpolationColors( cast(Gdip.LinearGradientBrush)handle, c.ptr, f.ptr, 3); Gdip.Color_delete(midColor); } Gdip.Color_delete(backColor); } Gdip.Color_delete(foreColor); - if (device.tracking) device.new_Object(this); + init_(); } -/** - * Disposes of the operating system resources associated with - * the Pattern. Applications must dispose of all Patterns that - * they allocate. - */ -override public void dispose() { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy() { int type = Gdip.Brush_GetType(handle); switch (type) { case Gdip.BrushTypeSolidColor: @@ -249,8 +238,6 @@ default: } handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/Region.d --- a/dwt/graphics/Region.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/Region.d Sat May 17 17:34:28 2008 +0200 @@ -38,6 +38,7 @@ */ public final class Region : Resource { + alias Resource.init_ init_; /** * the OS resource for the region @@ -82,12 +83,10 @@ * @since 3.0 */ public this (Device device) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); handle = OS.CreateRectRgn (0, 0, 0, 0); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); } /** @@ -97,7 +96,7 @@ * @param handle the handle for the result */ this(Device device, HRGN handle) { - this.device = device; + super(device); this.handle = handle; } @@ -233,18 +232,9 @@ return contains(pt.x, pt.y); } -/** - * Disposes of the operating system resources associated with - * the region. Applications must dispose of all regions which - * they allocate. - */ -override public void dispose () { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy () { OS.DeleteObject(handle); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/Resource.d --- a/dwt/graphics/Resource.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/Resource.d Sat May 17 17:34:28 2008 +0200 @@ -44,12 +44,30 @@ */ Device device; +this() { +} + +this(Device device) { + if (device is null) device = Device.getDevice(); + if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + this.device = device; +} + +void destroy() { +} + /** * Disposes of the operating system resources associated with * this resource. Applications must dispose of all resources * which they allocate. */ -public abstract void dispose(); +public void dispose() { + if (device is null) return; + if (device.isDisposed()) return; + destroy(); + if (device.tracking) device.dispose_Object(this); + device = null; +} /** * Returns the Device where this resource was @@ -65,6 +83,10 @@ return device; } +void init_() { + if (device.tracking) device.new_Object(this); +} + /** * Returns true if the resource has been disposed, * and false otherwise. diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/TextLayout.d --- a/dwt/graphics/TextLayout.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/TextLayout.d Sat May 17 17:34:28 2008 +0200 @@ -16,6 +16,7 @@ import dwt.DWTException; import dwt.internal.Compatibility; import dwt.internal.gdip.Gdip; + import dwt.internal.win32.OS; import dwt.graphics.Color; @@ -51,6 +52,8 @@ * @since 3.0 */ public final class TextLayout : Resource { + alias Resource.init_ init_; + Font font; String text, segmentsText; int lineSpacing; @@ -63,6 +66,7 @@ int[] tabs; int[] segments; StyleItem[] styles; + int stylesCount; StyleItem[] allRuns; StyleItem[][] runs; @@ -89,6 +93,11 @@ } } + /* IME has a copy of these constants */ + static const int UNDERLINE_IME_DOT = 1 << 16; + static const int UNDERLINE_IME_DASH = 2 << 16; + static const int UNDERLINE_IME_THICK = 3 << 16; + class StyleItem { TextStyle style; int start, length; @@ -112,6 +121,8 @@ int descent; int leading; int x; + int underlinePos, underlineThickness; + int strikeoutPos, strikeoutThickness; /* Justify info (malloc during computeRuns) */ int* justify; @@ -191,22 +202,21 @@ */ public this (Device device) { static_this(); - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; + super(device); wrapWidth = ascent = descent = -1; lineSpacing = 0; orientation = DWT.LEFT_TO_RIGHT; styles = new StyleItem[2]; styles[0] = new StyleItem(); styles[1] = new StyleItem(); + stylesCount = 2; text = ""; //$NON-NLS-1$ void* ppv; OS.OleInitialize(null); if (OS.CoCreateInstance(CLSID_CMultiLanguage.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_IMLangFontLink2.ptr, cast(void*)&ppv) is OS.S_OK) { mLangFontLink2 = ppv; } - if (device.tracking) device.new_Object(this); + init_(); } void breakRun(StyleItem run) { @@ -349,9 +359,15 @@ if (start is 0 && i !is lineStart && !run.tab) { run = allRuns[--i]; } else if (start <= 0 && i is lineStart) { - i = firstIndice; - run = allRuns[i]; - start = Math.max(1, firstStart); + if (lineWidth is wrapWidth && firstIndice > 0) { + i = firstIndice - 1; + run = allRuns[i]; + start = run.length; + } else { + i = firstIndice; + run = allRuns[i]; + start = Math.max(1, firstStart); + } } breakRun(run); while (start < run.length) { @@ -471,12 +487,7 @@ if (gc is null) device.internal_dispose_GC(hDC, null); } -/** - * Disposes of the operating system resources associated with - * the text layout. Applications must dispose of all allocated text layouts. - */ -override public void dispose () { - if (device is null) return; +void destroy () { freeRuns(); font = null; text = null; @@ -493,8 +504,6 @@ mLangFontLink2 = null; } OS.OleUninitialize(); - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -595,7 +604,7 @@ Gdip.Matrix_delete(identity_); if (!Gdip.Matrix_IsIdentity(matrix)) { lpXform = new float[6]; - Gdip.Matrix_GetElements(matrix, lpXform); + Gdip.Matrix_GetElements(matrix, lpXform.ptr); } Gdip.Matrix_delete(matrix); if ((data.style & DWT.MIRRORED) !is 0 && lpXform !is null) { @@ -642,26 +651,26 @@ selectionEnd = translateOffset(selectionEnd); } RECT rect; - void* selBrush; - void* selPen; - void* selBrushFg; + Gdip.Brush selBrush; + Gdip.Pen selPen; + Gdip.Brush selBrushFg; if (hasSelection || (flags & DWT.LAST_LINE_SELECTION) !is 0) { if (gdip) { auto bg = selectionBackground.handle; auto argb = ((alpha & 0xFF) << 24) | ((bg >> 16) & 0xFF) | (bg & 0xFF00) | ((bg & 0xFF) << 16); auto color = Gdip.Color_new(argb); - selBrush = Gdip.SolidBrush_new(color); + selBrush = cast(Gdip.Brush)Gdip.SolidBrush_new(color); Gdip.Color_delete(color); auto fg = selectionForeground.handle; argb = ((alpha & 0xFF) << 24) | ((fg >> 16) & 0xFF) | (fg & 0xFF00) | ((fg & 0xFF) << 16); color = Gdip.Color_new(argb); - selBrushFg = Gdip.SolidBrush_new(color); - selPen = Gdip.Pen_new( cast(Gdip.Brush)selBrushFg, 1); + selBrushFg = cast(Gdip.Brush)Gdip.SolidBrush_new(color); + selPen = cast(Gdip.Pen) Gdip.Pen_new( cast(Gdip.Brush)selBrushFg, 1); Gdip.Color_delete(color); } else { - selBrush = OS.CreateSolidBrush(selectionBackground.handle); - selPen = OS.CreatePen(OS.PS_SOLID, 1, selectionForeground.handle); + selBrush = cast(Gdip.Brush)OS.CreateSolidBrush(selectionBackground.handle); + selPen = cast(Gdip.Pen)OS.CreatePen(OS.PS_SOLID, 1, selectionForeground.handle); } } int offset = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? -1 : 0; @@ -670,7 +679,7 @@ int drawX = x + getLineIndent(line); int drawY = y + lineY[line]; StyleItem[] lineRuns = runs[line]; - int lineHeight = lineY[line+1] - lineY[line]; + int lineHeight = lineY[line+1] - lineY[line] - lineSpacing; if (flags !is 0 && (hasSelection || (flags & DWT.LAST_LINE_SELECTION) !is 0)) { bool extents = false; if (line is runs.length - 1 && (flags & DWT.LAST_LINE_SELECTION) !is 0) { @@ -691,21 +700,23 @@ if ((flags & DWT.FULL_SELECTION) !is 0) { width = OS.IsWin95 ? 0x7FFF : 0x6FFFFFF; } else { - width = (lineHeight - lineSpacing) / 3; + width = lineHeight / 3; } if (gdip) { - Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, drawX + lineWidth[line], drawY, width, lineHeight - lineSpacing); + Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, drawX + lineWidth[line], drawY, width, lineHeight); } else { OS.SelectObject(hdc, selBrush); - OS.PatBlt(hdc, drawX + lineWidth[line], drawY, width, lineHeight - lineSpacing, OS.PATCOPY); + OS.PatBlt(hdc, drawX + lineWidth[line], drawY, width, lineHeight, OS.PATCOPY); } } } if (drawX > clip.x + clip.width) continue; if (drawX + lineWidth[line] < clip.x) continue; int baseline = Math.max(0, this.ascent); + int lineUnderlinePos = 0; for (int i = 0; i < lineRuns.length; i++) { baseline = Math.max(baseline, lineRuns[i].ascent); + lineUnderlinePos = Math.min(lineUnderlinePos, lineRuns[i].underlinePos); } int alignmentX = drawX; for (int i = 0; i < lineRuns.length; i++) { @@ -718,26 +729,25 @@ bool fullSelection = hasSelection && selectionStart <= run.start && selectionEnd >= end; if (fullSelection) { if (gdip) { - Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, drawX, drawY, run.width, lineHeight - lineSpacing); + Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, drawX, drawY, run.width, lineHeight); } else { OS.SelectObject(hdc, selBrush); - OS.PatBlt(hdc, drawX, drawY, run.width, lineHeight - lineSpacing, OS.PATCOPY); + OS.PatBlt(hdc, drawX, drawY, run.width, lineHeight, OS.PATCOPY); } } else { if (run.style !is null && run.style.background !is null) { auto bg = run.style.background.handle; - int drawRunY = drawY + (baseline - run.ascent); if (gdip) { int argb = ((alpha & 0xFF) << 24) | ((bg >> 16) & 0xFF) | (bg & 0xFF00) | ((bg & 0xFF) << 16); auto color = Gdip.Color_new(argb); auto brush = Gdip.SolidBrush_new(color); - Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)brush, drawX, drawRunY, run.width, run.ascent + run.descent); + Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)brush, drawX, drawY, run.width, lineHeight); Gdip.Color_delete(color); Gdip.SolidBrush_delete(brush); } else { auto hBrush = OS.CreateSolidBrush (bg); auto oldBrush = OS.SelectObject(hdc, hBrush); - OS.PatBlt(hdc, drawX, drawRunY, run.width, run.ascent + run.descent, OS.PATCOPY); + OS.PatBlt(hdc, drawX, drawY, run.width, lineHeight, OS.PATCOPY); OS.SelectObject(hdc, oldBrush); OS.DeleteObject(hBrush); } @@ -757,8 +767,13 @@ OS.ScriptCPtoX(selEnd, true, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX); runX = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX; rect.right = drawX + runX; - rect.bottom = drawY + lineHeight - lineSpacing; + rect.bottom = drawY + lineHeight; if (gdip) { + if (rect.left > rect.right) { + int tmp = rect.left; + rect.left = rect.right; + rect.right = tmp; + } Gdip.Graphics_FillRectangle(gdipGraphics, cast(Gdip.Brush)selBrush, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); } else { OS.SelectObject(hdc, selBrush); @@ -770,6 +785,7 @@ } drawX += run.width; } + RECT* borderClip = null; drawX = alignmentX; for (int i = 0; i < lineRuns.length; i++) { StyleItem run = lineRuns[i]; @@ -819,7 +835,7 @@ if ((type & OS.PT_CLOSEFIGURE) !is 0) newType |= Gdip.PathPointTypeCloseSubpath; types[typeIndex] = cast(byte)newType; } - auto path = Gdip.GraphicsPath_new(cast(Gdip.Point[])points, types, count, Gdip.FillModeAlternate); + auto path = Gdip.GraphicsPath_new(cast(Gdip.Point*)points.ptr, types.ptr, count, Gdip.FillModeAlternate); if (path is null) DWT.error(DWT.ERROR_NO_HANDLES); auto brush = foregroundBrush; if (fullSelection) { @@ -865,46 +881,31 @@ Gdip.Graphics_Restore(gdipGraphics, gstate2); } Gdip.Graphics_SetSmoothingMode(gdipGraphics, antialias); - if (run.style !is null && (run.style.underline || run.style.strikeout)) { - auto newPen = hasSelection ? cast(Gdip.Pen)selPen : Gdip.Pen_new(brush, 1); - Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone); - if (run.style.underline) { - int underlineY = drawY + baseline + 1 - run.style.rise; - Gdip.Graphics_DrawLine(gdipGraphics, newPen, drawX, underlineY, drawX + run.width, underlineY); - } - if (run.style.strikeout) { - int strikeoutY = drawRunY + run.leading + (run.ascent - run.style.rise) / 2; - Gdip.Graphics_DrawLine(gdipGraphics, newPen, drawX, strikeoutY, drawX + run.width, strikeoutY); - } - if (cast(void*)newPen !is selPen) Gdip.Pen_delete(newPen); - Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf); - } + drawLines(gdip, gdipGraphics, x, drawY + baseline, lineUnderlinePos, drawY + lineHeight, lineRuns, i, brush, null, alpha); if (partialSelection) { Gdip.Graphics_Restore(gdipGraphics, gstate); gstate = Gdip.Graphics_Save(gdipGraphics); Gdip.Graphics_SetClip(gdipGraphics, &gdipRect, Gdip.CombineModeIntersect); Gdip.Graphics_SetSmoothingMode(gdipGraphics, textAntialias); - Gdip.Graphics_FillPath(gdipGraphics, cast(Gdip.Brush)selBrushFg, path); + if ((data.style & DWT.MIRRORED) !is 0) { + gstate2 = Gdip.Graphics_Save(gdipGraphics); + Gdip.Graphics_ScaleTransform(gdipGraphics, -1, 1, Gdip.MatrixOrderPrepend); + Gdip.Graphics_TranslateTransform(gdipGraphics, -2 * drawX - run.width, 0, Gdip.MatrixOrderPrepend); + } + Gdip.Graphics_FillPath(gdipGraphics, selBrushFg, path); + if ((data.style & DWT.MIRRORED) !is 0) { + Gdip.Graphics_Restore(gdipGraphics, gstate2); + } Gdip.Graphics_SetSmoothingMode(gdipGraphics, antialias); - if (run.style !is null && (run.style.underline || run.style.strikeout)) { - Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeNone); - if (run.style.underline) { - int underlineY = drawY + baseline + 1 - run.style.rise; - Gdip.Graphics_DrawLine(gdipGraphics, cast(Gdip.Pen)selPen, rect.left, underlineY, rect.right, underlineY); - } - if (run.style.strikeout) { - int strikeoutY = drawRunY + run.leading + (run.ascent - run.style.rise) / 2; - Gdip.Graphics_DrawLine(gdipGraphics, cast(Gdip.Pen)selPen, rect.left, strikeoutY, rect.right, strikeoutY); - } - Gdip.Graphics_SetPixelOffsetMode(gdipGraphics, Gdip.PixelOffsetModeHalf); - } + drawLines(gdip, gdipGraphics, x, drawY + baseline, lineUnderlinePos, drawY + lineHeight, lineRuns, i, selBrushFg, &rect, alpha); Gdip.Graphics_Restore(gdipGraphics, gstate); } + borderClip = drawBorder(gdip, gdipGraphics, x, drawY, lineHeight, foregroundBrush, selBrushFg, fullSelection, borderClip, partialSelection ? &rect : null, alpha, lineRuns, i, selectionStart, selectionEnd); Gdip.GraphicsPath_delete(path); if ( brush !is cast(Gdip.Brush)selBrushFg && brush !is cast(Gdip.Brush)foregroundBrush) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)brush); } else { - int fg = foreground; + auto fg = foreground; if (fullSelection) { fg = selectionForeground.handle; } else { @@ -912,40 +913,14 @@ } OS.SetTextColor(hdc, fg); OS.ScriptTextOut(hdc, run.psc, drawX + offset, drawRunY, 0, null, &run.analysis , null, 0, run.glyphs, run.glyphCount, run.advances, run.justify, run.goffsets); - if (run.style !is null && (run.style.underline || run.style.strikeout)) { - auto newPen = hasSelection && fg is selectionForeground.handle ? cast(HPEN)selPen : OS.CreatePen(OS.PS_SOLID, 1, fg); - auto oldPen = OS.SelectObject(hdc, newPen); - if (run.style.underline) { - int underlineY = drawY + baseline + 1 - run.style.rise; - OS.MoveToEx(hdc, drawX, underlineY, null); - OS.LineTo(hdc, drawX + run.width, underlineY); - } - if (run.style.strikeout) { - int strikeoutY = drawRunY + run.leading + (run.ascent - run.style.rise) / 2; - OS.MoveToEx(hdc, drawX, strikeoutY, null); - OS.LineTo(hdc, drawX + run.width, strikeoutY); - } - OS.SelectObject(hdc, oldPen); - if (!hasSelection || fg !is selectionForeground.handle) OS.DeleteObject(newPen); - } + drawLines(gdip, hdc, x, drawY + baseline, lineUnderlinePos, drawY + lineHeight, lineRuns, i, cast(void*)fg, null, alpha); if (partialSelection && fg !is selectionForeground.handle) { OS.SetTextColor(hdc, selectionForeground.handle); OS.ScriptTextOut(hdc, run.psc, drawX + offset, drawRunY, OS.ETO_CLIPPED, &rect, &run.analysis , null, 0, run.glyphs, run.glyphCount, run.advances, run.justify, run.goffsets); - if (run.style !is null && (run.style.underline || run.style.strikeout)) { - auto oldPen = OS.SelectObject(hdc, selPen); - if (run.style.underline) { - int underlineY = drawY + baseline + 1 - run.style.rise; - OS.MoveToEx(hdc, rect.left, underlineY, null); - OS.LineTo(hdc, rect.right, underlineY); - } - if (run.style.strikeout) { - int strikeoutY = drawRunY + run.leading + (run.ascent - run.style.rise) / 2; - OS.MoveToEx(hdc, rect.left, strikeoutY, null); - OS.LineTo(hdc, rect.right, strikeoutY); - } - OS.SelectObject(hdc, oldPen); - } + drawLines(gdip, hdc, x, drawY + baseline, lineUnderlinePos, drawY + lineHeight, lineRuns, i, cast(void*)selectionForeground.handle, &rect, alpha); } + int selForeground = selectionForeground !is null ? selectionForeground.handle : 0; + borderClip = drawBorder(gdip, hdc, x, drawY, lineHeight, cast(void*)foreground, cast(void*)selForeground, fullSelection, borderClip, partialSelection ? &rect : null, alpha, lineRuns, i, selectionStart, selectionEnd); } } } @@ -955,7 +930,7 @@ if (gdip) { if (selBrush !is null) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)selBrush); if (selBrushFg !is null) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)selBrushFg); - if (selPen !is null) Gdip.Pen_delete(cast(Gdip.Pen)selPen); + if (selPen !is null) Gdip.Pen_delete(selPen); } else { OS.RestoreDC(hdc, state); if (gdipGraphics !is null) Gdip.Graphics_ReleaseHDC(gdipGraphics, hdc); @@ -964,6 +939,355 @@ } } +void drawLines(bool advance, void* graphics, int x, int lineBaseline, int lineUnderlinePos, int lineBottom, StyleItem[] line, int index, void* color, RECT* clipRect, int alpha) { + StyleItem run = line[index]; + TextStyle style = run.style; + if (style is null) return; + if (!style.underline && !style.strikeout) return; + int runX = x + run.x; + int underlineY = lineBaseline - lineUnderlinePos; + int strikeoutY = lineBaseline - run.strikeoutPos; + if (advance) { + Gdip.Graphics_SetPixelOffsetMode(cast(Gdip.Graphics)graphics, Gdip.PixelOffsetModeNone); + auto brush = color; + if (style.underline) { + if (style.underlineColor !is null) { + int fg = style.underlineColor.handle; + int argb = ((alpha & 0xFF) << 24) | ((fg >> 16) & 0xFF) | (fg & 0xFF00) | ((fg & 0xFF) << 16); + auto gdiColor = Gdip.Color_new(argb); + brush = Gdip.SolidBrush_new(gdiColor); + Gdip.Color_delete(gdiColor); + } + switch (style.underlineStyle) { + case DWT.UNDERLINE_SQUIGGLE: + case DWT.UNDERLINE_ERROR: { + int squigglyThickness = 1; + int squigglyHeight = 2 * squigglyThickness; + int squigglyY = Math.min(underlineY - squigglyHeight / 2, lineBottom - squigglyHeight - 1); + int squigglyX = runX; + for (int i = index; i > 0 && style.isAdherentUnderline(line[i - 1].style); i--) { + squigglyX = x + line[i - 1].x; + } + int gstate = 0; + if (clipRect is null) { + gstate = Gdip.Graphics_Save(cast(Gdip.Graphics)graphics); + Gdip.Rect gdipRect; + gdipRect.X = runX; + gdipRect.Y = squigglyY; + gdipRect.Width = run.width + 1; + gdipRect.Height = squigglyY + squigglyHeight + 1; + Gdip.Graphics_SetClip(cast(Gdip.Graphics)graphics, &gdipRect, Gdip.CombineModeIntersect); + } + int[] points = computePolyline(squigglyX, squigglyY, runX + run.width, squigglyY + squigglyHeight); + auto pen = Gdip.Pen_new(cast(Gdip.Brush)brush, squigglyThickness); + Gdip.Graphics_DrawLines(cast(Gdip.Graphics)graphics, pen, cast(Gdip.Point*)points.ptr, points.length / 2); + Gdip.Pen_delete(pen); + if (gstate !is 0) Gdip.Graphics_Restore(cast(Gdip.Graphics)graphics, gstate); + break; + } + case DWT.UNDERLINE_SINGLE: + Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX, underlineY, run.width, run.underlineThickness); + break; + case DWT.UNDERLINE_DOUBLE: + Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX, underlineY, run.width, run.underlineThickness); + Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX, underlineY + run.underlineThickness * 2, run.width, run.underlineThickness); + break; + case UNDERLINE_IME_THICK: + Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX - run.underlineThickness, underlineY, run.width, run.underlineThickness * 2); + break; + case UNDERLINE_IME_DOT: + case UNDERLINE_IME_DASH: { + auto pen = Gdip.Pen_new(cast(Gdip.Brush)brush, 1); + int dashStyle = style.underlineStyle is UNDERLINE_IME_DOT ? Gdip.DashStyleDot : Gdip.DashStyleDash; + Gdip.Pen_SetDashStyle(pen, dashStyle); + Gdip.Graphics_DrawLine(cast(Gdip.Graphics)graphics, pen, runX, underlineY, runX + run.width, underlineY); + Gdip.Pen_delete(pen); + break; + } + } + if (brush !is color) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)brush); + } + if (style.strikeout) { + if (style.strikeoutColor !is null) { + int fg = style.strikeoutColor.handle; + int argb = ((alpha & 0xFF) << 24) | ((fg >> 16) & 0xFF) | (fg & 0xFF00) | ((fg & 0xFF) << 16); + auto gdiColor = Gdip.Color_new(argb); + brush = Gdip.SolidBrush_new(gdiColor); + Gdip.Color_delete(gdiColor); + } + Gdip.Graphics_FillRectangle(cast(Gdip.Graphics)graphics, cast(Gdip.Brush)brush, runX, strikeoutY, run.width, run.strikeoutThickness); + if (brush !is color) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)brush); + } + Gdip.Graphics_SetPixelOffsetMode(cast(Gdip.Graphics)graphics, Gdip.PixelOffsetModeHalf); + } else { + uint colorRefUnderline = cast(uint)color; + uint colorRefStrikeout = cast(uint)color; + int /*long*/ brushUnderline = 0; + int /*long*/ brushStrikeout = 0; + RECT rect; + if (style.underline) { + if (style.underlineColor !is null) { + colorRefUnderline = style.underlineColor.handle; + } + switch (style.underlineStyle) { + case DWT.UNDERLINE_SQUIGGLE: + case DWT.UNDERLINE_ERROR: { + int squigglyThickness = 1; + int squigglyHeight = 2 * squigglyThickness; + int squigglyY = Math.min(underlineY - squigglyHeight / 2, lineBottom - squigglyHeight - 1); + int squigglyX = runX; + for (int i = index; i > 0 && style.isAdherentUnderline(line[i - 1].style); i--) { + squigglyX = x + line[i - 1].x; + } + int state = OS.SaveDC(graphics); + if (clipRect !is null) { + OS.IntersectClipRect(graphics, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom); + } else { + OS.IntersectClipRect(graphics, runX, squigglyY, runX + run.width + 1, squigglyY + squigglyHeight + 1); + } + int[] points = computePolyline(squigglyX, squigglyY, runX + run.width, squigglyY + squigglyHeight); + auto pen = OS.CreatePen(OS.PS_SOLID, squigglyThickness, colorRefUnderline); + auto oldPen = OS.SelectObject(graphics, pen); + OS.Polyline(graphics, cast(POINT*)points.ptr, points.length / 2); + int length_ = points.length; + if (length_ >= 2 && squigglyThickness <= 1) { + OS.SetPixel (graphics, points[length_ - 2], points[length_ - 1], colorRefUnderline); + } + OS.RestoreDC(graphics, state); + OS.SelectObject(graphics, oldPen); + OS.DeleteObject(pen); + break; + } + case DWT.UNDERLINE_SINGLE: + brushUnderline = cast(uint) OS.CreateSolidBrush(colorRefUnderline); + OS.SetRect(&rect, runX, underlineY, runX + run.width, underlineY + run.underlineThickness); + if (clipRect !is null) { + rect.left = Math.max(rect.left, clipRect.left); + rect.right = Math.min(rect.right, clipRect.right); + } + OS.FillRect(graphics, &rect, cast(void*)brushUnderline); + break; + case DWT.UNDERLINE_DOUBLE: + brushUnderline = cast(uint)OS.CreateSolidBrush(colorRefUnderline); + OS.SetRect(&rect, runX, underlineY, runX + run.width, underlineY + run.underlineThickness); + if (clipRect !is null) { + rect.left = Math.max(rect.left, clipRect.left); + rect.right = Math.min(rect.right, clipRect.right); + } + OS.FillRect(graphics, &rect, cast(void*)brushUnderline); + OS.SetRect(&rect, runX, underlineY + run.underlineThickness * 2, runX + run.width, underlineY + run.underlineThickness * 3); + if (clipRect !is null) { + rect.left = Math.max(rect.left, clipRect.left); + rect.right = Math.min(rect.right, clipRect.right); + } + OS.FillRect(graphics, &rect, cast(void*)brushUnderline); + break; + case UNDERLINE_IME_THICK: + brushUnderline = cast(uint)OS.CreateSolidBrush(colorRefUnderline); + OS.SetRect(&rect, runX, underlineY - run.underlineThickness, runX + run.width, underlineY + run.underlineThickness); + if (clipRect !is null) { + rect.left = Math.max(rect.left, clipRect.left); + rect.right = Math.min(rect.right, clipRect.right); + } + OS.FillRect(graphics, &rect, cast(void*)brushUnderline); + break; + case UNDERLINE_IME_DASH: + case UNDERLINE_IME_DOT: { + underlineY = lineBaseline + run.descent; + int penStyle = style.underlineStyle is UNDERLINE_IME_DASH ? OS.PS_DASH : OS.PS_DOT; + auto pen = OS.CreatePen(penStyle, 1, colorRefUnderline); + auto oldPen = OS.SelectObject(graphics, pen); + OS.SetRect(&rect, runX, underlineY, runX + run.width, underlineY + run.underlineThickness); + if (clipRect !is null) { + rect.left = Math.max(rect.left, clipRect.left); + rect.right = Math.min(rect.right, clipRect.right); + } + OS.MoveToEx(graphics, rect.left, rect.top, null); + OS.LineTo(graphics, rect.right, rect.top); + OS.SelectObject(graphics, oldPen); + OS.DeleteObject(pen); + break; + } + } + } + if (style.strikeout) { + if (style.strikeoutColor !is null) { + colorRefStrikeout = style.strikeoutColor.handle; + } + if (brushUnderline !is 0 && colorRefStrikeout is colorRefUnderline) { + brushStrikeout = brushUnderline; + } else { + brushStrikeout = cast(int) OS.CreateSolidBrush(colorRefStrikeout); + } + OS.SetRect(&rect, runX, strikeoutY, runX + run.width, strikeoutY + run.strikeoutThickness); + if (clipRect !is null) { + rect.left = Math.max(rect.left, clipRect.left); + rect.right = Math.min(rect.right, clipRect.right); + } + OS.FillRect(graphics, &rect, cast(void*)brushStrikeout); + } + if (brushUnderline !is 0) OS.DeleteObject(cast(void*)brushUnderline); + if (brushStrikeout !is 0 && brushStrikeout !is brushUnderline) OS.DeleteObject(cast(void*)brushStrikeout); + } +} + +RECT* drawBorder(bool advance, void* graphics, int x, int y, int lineHeight, void* color, void* selectionColor, bool fullSelection, RECT* clipRect, RECT* rect, int alpha, StyleItem[] line, int index, int selectionStart, int selectionEnd) { + StyleItem run = line[index]; + TextStyle style = run.style; + if (style is null) return null; + if (style.borderStyle is DWT.NONE) return null; + if (rect !is null) { + if (clipRect is null) { + clipRect = new RECT (); + OS.SetRect(clipRect, -1, rect.top, -1, rect.bottom); + } + bool isRTL = (orientation & DWT.RIGHT_TO_LEFT) !is 0; + if (run.start <= selectionStart && selectionStart <= run.start + run.length) { + if (run.analysis.fRTL ^ isRTL) { + clipRect.right = rect.left; + } else { + clipRect.left = rect.left; + } + } + if (run.start <= selectionEnd && selectionEnd <= run.start + run.length) { + if (run.analysis.fRTL ^ isRTL) { + clipRect.left = rect.right; + } else { + clipRect.right = rect.right; + } + } + } + if (index + 1 >= line.length || !style.isAdherentBorder(line[index + 1].style)) { + int left = run.x; + for (int i = index; i > 0 && style.isAdherentBorder(line[i - 1].style); i--) { + left = line[i - 1].x; + } + if (advance) { + auto brush = color; + int customColor = -1; + if (style.borderColor !is null) { + customColor = style.borderColor.handle; + } else { + if (style.foreground !is null) { + customColor = style.foreground.handle; + } + if (fullSelection && clipRect is null) { + customColor = -1; + brush = selectionColor; + } + } + if (customColor !is -1) { + int argb = ((alpha & 0xFF) << 24) | ((customColor >> 16) & 0xFF) | (customColor & 0xFF00) | ((customColor & 0xFF) << 16); + auto gdiColor = Gdip.Color_new(argb); + brush = Gdip.SolidBrush_new(gdiColor); + Gdip.Color_delete(gdiColor); + } + int lineWidth = 1; + int lineStyle = Gdip.DashStyleSolid; + switch (style.borderStyle) { + case DWT.BORDER_SOLID: break; + case DWT.BORDER_DASH: lineStyle = Gdip.DashStyleDash; break; + case DWT.BORDER_DOT: lineStyle = Gdip.DashStyleDot; break; + } + auto pen = Gdip.Pen_new(cast(Gdip.Brush)brush, lineWidth); + Gdip.Pen_SetDashStyle(pen, lineStyle); + float gdipXOffset = 0.5f, gdipYOffset = 0.5f; + Gdip.Graphics_TranslateTransform(cast(Gdip.Graphics)graphics, gdipXOffset, gdipYOffset, Gdip.MatrixOrderPrepend); + if (style.borderColor is null && clipRect !is null) { + int gstate = Gdip.Graphics_Save(cast(Gdip.Graphics)graphics); + if (clipRect.left is -1) clipRect.left = 0; + if (clipRect.right is -1) clipRect.right = 0x7ffff; + Gdip.Rect gdipRect; + gdipRect.X = clipRect.left; + gdipRect.Y = clipRect.top; + gdipRect.Width = clipRect.right - clipRect.left; + gdipRect.Height = clipRect.bottom - clipRect.top; + Gdip.Graphics_SetClip(cast(Gdip.Graphics)graphics, &gdipRect, Gdip.CombineModeExclude); + Gdip.Graphics_DrawRectangle(cast(Gdip.Graphics)graphics, pen, x + left, y, run.x + run.width - left - 1, lineHeight - 1); + Gdip.Graphics_Restore(cast(Gdip.Graphics)graphics, gstate); + gstate = Gdip.Graphics_Save(cast(Gdip.Graphics)graphics); + Gdip.Graphics_SetClip(cast(Gdip.Graphics)graphics, &gdipRect, Gdip.CombineModeIntersect); + auto selPen = Gdip.Pen_new(cast(Gdip.Brush)selectionColor, lineWidth); + Gdip.Pen_SetDashStyle(pen, lineStyle); + Gdip.Graphics_DrawRectangle(cast(Gdip.Graphics)graphics, selPen, x + left, y, run.x + run.width - left - 1, lineHeight - 1); + Gdip.Pen_delete(selPen); + Gdip.Graphics_Restore(cast(Gdip.Graphics)graphics, gstate); + } else { + Gdip.Graphics_DrawRectangle(cast(Gdip.Graphics)graphics, pen, x + left, y, run.x + run.width - left - 1, lineHeight - 1); + } + Gdip.Graphics_TranslateTransform(cast(Gdip.Graphics)graphics, -gdipXOffset, -gdipYOffset, Gdip.MatrixOrderPrepend); + Gdip.Pen_delete(pen); + if (customColor !is -1) Gdip.SolidBrush_delete(cast(Gdip.SolidBrush)brush); + } else { + if (style.borderColor !is null) { + color = cast(void*)style.borderColor.handle; + } else { + if (style.foreground !is null) { + color = cast(void*)style.foreground.handle; + } + if (fullSelection && clipRect is null) { + color = selectionColor; + } + } + int lineWidth = 1; + int lineStyle = OS.PS_SOLID; + switch (style.borderStyle) { + case DWT.BORDER_SOLID: break; + case DWT.BORDER_DASH: lineStyle = OS.PS_DASH; break; + case DWT.BORDER_DOT: lineStyle = OS.PS_DOT; break; + } + LOGBRUSH logBrush; + logBrush.lbStyle = OS.BS_SOLID; + logBrush.lbColor = cast(uint)color; + auto newPen = OS.ExtCreatePen(lineStyle | OS.PS_GEOMETRIC, Math.max(1, lineWidth), &logBrush, 0, null); + auto oldPen = OS.SelectObject(graphics, newPen); + auto oldBrush = OS.SelectObject(graphics, OS.GetStockObject(OS.NULL_BRUSH)); + OS.Rectangle(graphics, x + left, y, x + run.x + run.width, y + lineHeight); + if (style.borderColor is null && clipRect !is null && color !is selectionColor) { + int state = OS.SaveDC(graphics); + if (clipRect.left is -1) clipRect.left = 0; + if (clipRect.right is -1) clipRect.right = 0x7ffff; + OS.IntersectClipRect(graphics, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom); + logBrush.lbColor = cast(uint)selectionColor; + auto selPen = OS.ExtCreatePen (lineStyle | OS.PS_GEOMETRIC, Math.max(1, lineWidth), &logBrush, 0, null); + OS.SelectObject(graphics, selPen); + OS.Rectangle(graphics, x + left, y, x + run.x + run.width, y + lineHeight); + OS.RestoreDC(graphics, state); + OS.SelectObject(graphics, newPen); + OS.DeleteObject(selPen); + } + OS.SelectObject(graphics, oldBrush); + OS.SelectObject(graphics, oldPen); + OS.DeleteObject(newPen); + } + return null; + } + return clipRect; +} + +int[] computePolyline(int left, int top, int right, int bottom) { + int height = bottom - top; // can be any number + int width = 2 * height; // must be even + int peaks = Compatibility.ceil(right - left, width); + if (peaks is 0 && right - left > 2) { + peaks = 1; + } + int length_ = ((2 * peaks) + 1) * 2; + if (length_ < 0) return new int[0]; + + int[] coordinates = new int[length_]; + for (int i = 0; i < peaks; i++) { + int index = 4 * i; + coordinates[index] = left + (width * i); + coordinates[index+1] = bottom; + coordinates[index+2] = coordinates[index] + width / 2; + coordinates[index+3] = top; + } + coordinates[length_-2] = left + (width * peaks); + coordinates[length_-1] = bottom; + return coordinates; +} + void freeRuns () { if (allRuns is null) return; for (int i=0; i *
  • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
  • * + * + * @see #setWidth(int) + * @see #getLineBounds(int) */ public Rectangle getBounds () { checkLayout(); @@ -1050,11 +1379,11 @@ public Rectangle getBounds (int start, int end) { checkLayout(); computeRuns(null); - int length = text.length; - if (length is 0) return new Rectangle(0, 0, 0, 0); + int length_ = text.length; + if (length_ is 0) return new Rectangle(0, 0, 0, 0); if (start > end) return new Rectangle(0, 0, 0, 0); - start = Math.min(Math.max(0, start), length - 1); - end = Math.min(Math.max(0, end), length - 1); + start = Math.min(Math.max(0, start), length_ - 1); + end = Math.min(Math.max(0, end), length_ - 1); start = translateOffset(start); end = translateOffset(end); int left = 0x7fffffff, right = 0; @@ -1187,7 +1516,7 @@ if (this.font !is null) { return this.font.handle; } - return device.systemFont; + return device.systemFont.handle; } /** @@ -1207,8 +1536,8 @@ public int getLevel (int offset) { checkLayout(); computeRuns(null); - int length = text.length; - if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE); + int length_ = text.length; + if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE); offset = translateOffset(offset); for (int i=1; i offset) { @@ -1306,8 +1635,8 @@ public int getLineIndex (int offset) { checkLayout(); computeRuns(null); - int length = text.length; - if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE); + int length_ = text.length; + if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE); offset = translateOffset(offset); for (int line=0; line offset) { @@ -1337,7 +1666,7 @@ auto hDC = device.internal_new_GC(null); auto srcHdc = OS.CreateCompatibleDC(hDC); TEXTMETRIC lptm; - OS.SelectObject(srcHdc, font !is null ? font.handle : device.systemFont); + OS.SelectObject(srcHdc, font !is null ? font.handle : device.systemFont.handle); OS.GetTextMetrics(srcHdc, &lptm); OS.DeleteDC(srcHdc); device.internal_dispose_GC(hDC, null); @@ -1404,53 +1733,47 @@ public Point getLocation (int offset, bool trailing) { checkLayout(); computeRuns(null); - int length = text.length; - if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE); - length = segmentsText.length; + int length_ = text.length; + if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE); + length_ = segmentsText.length; offset = translateOffset(offset); int line; for (line=0; line offset) break; } line = Math.min(line, runs.length - 1); - StyleItem[] lineRuns = runs[line]; - Point result = null; - if (offset is length) { - result = new Point(lineWidth[line], lineY[line]); - } else { - int width = 0; - for (int i=0; i 1) { + int index = ((high + low) / 2); + StyleItem run = allRuns[index]; + if (run.start > offset) { + high = index; + } else if (run.start + run.length <= offset) { + low = index; + } else { + int width; + if (run.style !is null && run.style.metrics !is null) { + GlyphMetrics metrics = run.style.metrics; + width = metrics.width * (offset - run.start + (trailing ? 1 : 0)); + } else if (run.tab) { + width = (trailing || (offset is length_)) ? run.width : 0; + } else { + int runOffset = offset - run.start; + int cChars = run.length; + int gGlyphs = run.glyphCount; + int piX; + int* advances = run.justify !is null ? run.justify : run.advances; + OS.ScriptCPtoX(runOffset, trailing, cChars, gGlyphs, run.clusters, run.visAttrs, advances, &run.analysis, &piX); + width = (orientation & DWT.RIGHT_TO_LEFT) !is 0 ? run.width - piX : piX; } - width += run.width; + return new Point(run.x + width, lineY[line]); } } - if (result is null) result = new Point(0, 0); - result.x += getLineIndent(line); - return result; + return new Point(0, 0); } /** @@ -1479,13 +1802,13 @@ int _getOffset(int offset, int movement, bool forward) { computeRuns(null); - int length = text.length; - if (!(0 <= offset && offset <= length)) DWT.error(DWT.ERROR_INVALID_RANGE); - if (forward && offset is length) return length; + int length_ = text.length; + if (!(0 <= offset && offset <= length_)) DWT.error(DWT.ERROR_INVALID_RANGE); + if (forward && offset is length_) return length_; if (!forward && offset is 0) return 0; int step = forward ? 1 : -1; if ((movement & DWT.MOVEMENT_CHAR) !is 0) return offset + step; - length = segmentsText.length; + length_ = segmentsText.length; offset = translateOffset(offset); SCRIPT_LOGATTR* logAttr; SCRIPT_PROPERTIES* properties; @@ -1545,7 +1868,7 @@ } } i += step; - } while (0 <= i && i < allRuns.length - 1 && 0 <= offset && offset < length); + } while (0 <= i && i < allRuns.length - 1 && 0 <= offset && offset < length_); return forward ? text.length : 0; } @@ -1611,16 +1934,22 @@ if (lineY[line + 1] > y) break; } line = Math.min(line, runs.length - 1); - x -= getLineIndent(line); StyleItem[] lineRuns = runs[line]; - if (x >= lineWidth[line]) x = lineWidth[line] - 1; - if (x < 0) x = 0; - int width = 0; - for (int i = 0; i < lineRuns.length; i++) { - StyleItem run = lineRuns[i]; - if (run.lineBreak && !run.softBreak) return untranslateOffset(run.start); - if (width + run.width > x) { - int xRun = x - width; + int lineIndent = getLineIndent(line); + if (x >= lineIndent + lineWidth[line]) x = lineIndent + lineWidth[line] - 1; + if (x < lineIndent) x = lineIndent; + int low = -1; + int high = lineRuns.length; + while (high - low > 1) { + int index = ((high + low) / 2); + StyleItem run = lineRuns[index]; + if (run.x > x) { + high = index; + } else if (run.x + run.width <= x) { + low = index; + } else { + if (run.lineBreak && !run.softBreak) return untranslateOffset(run.start); + int xRun = x - run.x; if (run.style !is null && run.style.metrics !is null) { GlyphMetrics metrics = run.style.metrics; if (metrics.width > 0) { @@ -1631,7 +1960,7 @@ } } if (run.tab) { - if (trailing !is null) trailing[0] = x < (width + run.width / 2) ? 0 : 1; + if (trailing !is null) trailing[0] = x < (run.x + run.width / 2) ? 0 : 1; return untranslateOffset(run.start); } int cChars = run.length; @@ -1646,7 +1975,6 @@ if (trailing !is null) trailing[0] = piTrailing; return untranslateOffset(run.start + piCP); } - width += run.width; } if (trailing !is null) trailing[0] = 0; return untranslateOffset(lineOffset[line + 1]); @@ -1706,9 +2034,9 @@ */ public int[] getRanges () { checkLayout(); - int[] result = new int[styles.length * 2]; + int[] result = new int[stylesCount * 2]; int count = 0; - for (int i=0; i offset) { return styles[i - 1].style; } @@ -1818,9 +2146,9 @@ */ public TextStyle[] getStyles () { checkLayout(); - TextStyle[] result = new TextStyle[styles.length]; + TextStyle[] result = new TextStyle[stylesCount]; int count = 0; - for (int i=0; i stylesCount) { + StyleItem[] newStyles = new StyleItem[stylesCount]; + System.arraycopy(styles, 0, newStyles, 0, stylesCount); + styles = newStyles; + } int count = 0, start = 0, end = segmentsText.length, itemIndex = 0, styleIndex = 0; - StyleItem[] runs = new StyleItem[itemCount + styles.length]; - SCRIPT_ITEM* scriptItem; + StyleItem[] runs = new StyleItem[itemCount + stylesCount]; + SCRIPT_ITEM* scriptItem = new SCRIPT_ITEM(); bool linkBefore = false; while (start < end) { StyleItem item = new StyleItem(); item.start = start; item.style = styles[styleIndex].style; runs[count++] = item; - scriptItem = items + itemIndex; + *scriptItem = items[itemIndex]; item.analysis = scriptItem.a; if (linkBefore) { item.analysis.fLinkBefore = true; linkBefore = false; } //scriptItem.a = new SCRIPT_ANALYSIS(); - scriptItem = items + (itemIndex + 1); + *scriptItem = items[ itemIndex + 1]; int itemLimit = scriptItem.iCharPos; int styleLimit = translateOffset(styles[styleIndex + 1].start); if (styleLimit <= itemLimit) { @@ -1951,7 +2284,7 @@ if (start < itemLimit && 0 < start && start < end) { char pChar = segmentsText.charAt(start - 1); char tChar = segmentsText.charAt(start); - if (!Compatibility.isWhitespace(pChar) && !Compatibility.isWhitespace(tChar)) { + if (Compatibility.isLetter(pChar) && Compatibility.isLetter(tChar)) { item.analysis.fLinkAfter = true; linkBefore = true; } @@ -1965,7 +2298,7 @@ } StyleItem item = new StyleItem(); item.start = end; - scriptItem = items + itemCount; + *scriptItem = items[ itemCount ]; item.analysis = scriptItem.a; runs[count++] = item; if (runs.length !is count) { @@ -2114,10 +2447,11 @@ public void setFont (Font font) { checkLayout(); if (font !is null && font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - if (this.font is font) return; - if (font !is null && font ==/*eq*/ this.font) return; + Font oldFont = this.font; + if (oldFont is font) return; + this.font = font; + if (oldFont !is null && oldFont.opEquals(font)) return; freeRuns(); - this.font = font; } /** @@ -2256,7 +2590,7 @@ start = Math.min(Math.max(0, start), length_ - 1); end = Math.min(Math.max(0, end), length_ - 1); int low = -1; - int high = styles.length; + int high = stylesCount; while (high - low > 1) { int index = (high + low) / 2; if (styles[index + 1].start > start) { @@ -2265,7 +2599,7 @@ low = index; } } - if (0 <= high && high < styles.length) { + if (0 <= high && high < stylesCount) { StyleItem item = styles[high]; if (item.start is start && styles[high + 1].start - 1 is end) { if (style is null) { @@ -2278,7 +2612,7 @@ freeRuns(); int modifyStart = high; int modifyEnd = modifyStart; - while (modifyEnd < styles.length) { + while (modifyEnd < stylesCount) { if (styles[modifyEnd + 1].start > end) break; modifyEnd++; } @@ -2290,33 +2624,42 @@ return; } if (styleStart !is start && styleEnd !is end) { - StyleItem[] newStyles = new StyleItem[styles.length + 2]; - System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1); + int newLength = stylesCount + 2; + if (newLength > styles.length) { + int newSize = Math.min(newLength + 1024, Math.max(64, newLength * 2)); + StyleItem[] newStyles = new StyleItem[newSize]; + System.arraycopy(styles, 0, newStyles, 0, stylesCount); + styles = newStyles; + } + System.arraycopy(styles, modifyEnd + 1, styles, modifyEnd + 3, stylesCount - modifyEnd - 1); StyleItem item = new StyleItem(); item.start = start; item.style = style; - newStyles[modifyStart + 1] = item; + styles[modifyStart + 1] = item; item = new StyleItem(); item.start = end + 1; item.style = styles[modifyStart].style; - newStyles[modifyStart + 2] = item; - System.arraycopy(styles, modifyEnd + 1, newStyles, modifyEnd + 3, styles.length - modifyEnd - 1); - styles = newStyles; + styles[modifyStart + 2] = item; + stylesCount = newLength; return; } } if (start is styles[modifyStart].start) modifyStart--; if (end is styles[modifyEnd + 1].start - 1) modifyEnd++; - int newLength = styles.length + 1 - (modifyEnd - modifyStart - 1); - StyleItem[] newStyles = new StyleItem[newLength]; - System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1); + int newLength = stylesCount + 1 - (modifyEnd - modifyStart - 1); + if (newLength > styles.length) { + int newSize = Math.min(newLength + 1024, Math.max(64, newLength * 2)); + StyleItem[] newStyles = new StyleItem[newSize]; + System.arraycopy(styles, 0, newStyles, 0, stylesCount); + styles = newStyles; + } + System.arraycopy(styles, modifyEnd, styles, modifyStart + 2, stylesCount - modifyEnd); StyleItem item = new StyleItem(); item.start = start; item.style = style; - newStyles[modifyStart + 1] = item; - styles[modifyEnd].start = end + 1; - System.arraycopy(styles, modifyEnd, newStyles, modifyStart + 2, styles.length - modifyEnd); - styles = newStyles; + styles[modifyStart + 1] = item; + styles[modifyStart + 2].start = end + 1; + stylesCount = newLength; } /** @@ -2369,6 +2712,7 @@ styles[0] = new StyleItem(); styles[1] = new StyleItem(); styles[1].start = text.length; + stylesCount = 2; } /** @@ -2419,12 +2763,21 @@ return false; } +struct CallbackDataEnumFontFamExProc { + int delegate ( ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, int FontType, int lParam) EnumFontFamExProc; + int lParam; +} +extern(Windows) private static int EnumFontFamExProcFunc( ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, int FontType, int lParam) { + auto cb = cast(CallbackDataEnumFontFamExProc*)cast(void*)lParam; + return cb.EnumFontFamExProc( lpelfe, lpntme, FontType, cb.lParam ); +} + /* * Generate glyphs for one Run. */ void shape (HDC hdc, StyleItem run) { - int[] buffer = new int[1]; - char[] chars = new char[run.length]; + final int[] buffer = new int[1]; + final char[] chars = new char[run.length]; segmentsText.getChars(run.start, run.start + run.length, chars, 0); wchar[] wchars = StrToWCHARs( chars ); int maxGlyphs = (chars.length * 3 / 2) + 16; @@ -2435,9 +2788,29 @@ if (run.clusters is null) DWT.error(DWT.ERROR_NO_HANDLES); run.visAttrs = cast(SCRIPT_VISATTR*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, maxGlyphs * SCRIPT_VISATTR_SIZEOF); if (run.visAttrs is null) DWT.error(DWT.ERROR_NO_HANDLES); - run.psc = cast(SCRIPT_CACHE*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, 4); + run.psc = cast(SCRIPT_CACHE*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, (void*).sizeof); if (run.psc is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (!shape(hdc, run, chars, buffer, maxGlyphs)) { + bool shapeSucceed = shape(hdc, run, chars, buffer, maxGlyphs); + final short script = run.analysis.eScript; + + if (!shapeSucceed) { + /* + * Shape failed. + * Try to shape with fNoGlyphIndex when the run is in the + * Private Use Area. This allows for end-user-defined character (EUDC). + */ + auto properties = device.scripts[script]; + if (properties.fPrivateUseArea) { + run.analysis.fNoGlyphIndex = true; + shapeSucceed = shape(hdc, run, chars, buffer, maxGlyphs); + } + } + + if (!shapeSucceed) { + /* + * Shape Failed. + * Try to use MLANG to find a suitable font to shape the run. + */ if (mLangFontLink2 !is null) { int dwCodePages; int cchCodePages; @@ -2447,52 +2820,152 @@ /* MapFont() */ if (OS.VtblCall(10, mLangFontLink2, cast(int)hdc, dwCodePages, cast(int)wchars[0], cast(int)hNewFont) is OS.S_OK) { auto hFont = OS.SelectObject(hdc, hNewFont); - if (shape(hdc, run, chars, buffer, maxGlyphs)) { + shapeSucceed = shape(hdc, run, chars, buffer, maxGlyphs); + if (shapeSucceed) { run.fallbackFont = hNewFont; } else { /* ReleaseFont() */ OS.VtblCall(8, mLangFontLink2, cast(int)hNewFont); OS.SelectObject(hdc, hFont); - SCRIPT_PROPERTIES* properties; - properties = device.scripts[run.analysis.eScript]; - if (properties.fPrivateUseArea) { - run.analysis.fNoGlyphIndex = true; - } - OS.ScriptShape(hdc, run.psc, wchars.ptr, wchars.length, maxGlyphs, &run.analysis, run.glyphs, run.clusters, run.visAttrs, buffer.ptr); - run.glyphCount = buffer[0]; } } } } - ABC abc; + + if (!shapeSucceed) { + /* + * Shape Failed. + * Try to shape the run using the LOGFONT in the cache. + */ + auto hFont = OS.GetCurrentObject(hdc, OS.OBJ_FONT); + LOGFONT logFont; + OS.GetObject(hFont, LOGFONT.sizeof, &logFont); + + LOGFONT* cachedLogFont = device.logFontsCache !is null ? device.logFontsCache[script] : null; + if (cachedLogFont !is null) { + cachedLogFont.lfHeight = logFont.lfHeight; + cachedLogFont.lfWeight = logFont.lfWeight; + cachedLogFont.lfItalic = logFont.lfItalic; + cachedLogFont.lfWidth = logFont.lfWidth; + auto newFont = OS.CreateFontIndirect(cachedLogFont); + OS.SelectObject(hdc, newFont); + shapeSucceed = shape(hdc, run, chars, buffer, maxGlyphs); + if (shapeSucceed) { + run.fallbackFont = newFont; + } else { + OS.SelectObject(hdc, hFont); + OS.DeleteObject(newFont); + } + } + if (!shapeSucceed) { + /* + * Shape Failed. + * Use EnumFontFamExProc to iterate over every font in the system that supports + * the charset of the run and try to shape it. + */ + if (device.logFontsCache is null) device.logFontsCache = new LOGFONT*[device.scripts.length]; + LOGFONT newLogFont; + + int EnumFontFamExProc( ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, int FontType, int lParam) { + OS.MoveMemory(&newLogFont, cast(void*)lpelfe, LOGFONT.sizeof); + if (FontType is OS.RASTER_FONTTYPE) return 1; + newLogFont.lfHeight = logFont.lfHeight; + newLogFont.lfWeight = logFont.lfWeight; + newLogFont.lfItalic = logFont.lfItalic; + newLogFont.lfWidth = logFont.lfWidth; + auto newFont = OS.CreateFontIndirect(&newLogFont); + OS.SelectObject(hdc, newFont); + if (shape(hdc, run, chars, buffer, maxGlyphs)) { + run.fallbackFont = newFont; + LOGFONT* cacheLogFont = new LOGFONT(); + OS.MoveMemory(cacheLogFont, lpelfe, LOGFONT.sizeof); + device.logFontsCache[script] = cacheLogFont; + return 0; + } + OS.SelectObject(hdc, hFont); + OS.DeleteObject(newFont); + return 1; + } + CallbackDataEnumFontFamExProc cb; + cb.EnumFontFamExProc = &EnumFontFamExProc; + cb.lParam = 0; + auto properties = device.scripts[script]; + int charSet = properties.fAmbiguousCharSet ? OS.DEFAULT_CHARSET : properties.bCharSet; + newLogFont.lfCharSet = cast(byte)charSet; + OS.EnumFontFamiliesEx(hdc, &newLogFont, &EnumFontFamExProcFunc, cast(int) &cb, 0); + shapeSucceed = run.fallbackFont !is null; + } + } + + if (!shapeSucceed) { + /* + * Shape Failed. + * Give up and shape the run with the default font. + * Missing glyphs typically will be represent as black boxes in the text. + */ + auto wchars_ = StrToWCHARs(chars); + OS.ScriptShape(hdc, run.psc, wchars_.ptr, wchars_.length, maxGlyphs, &run.analysis, run.glyphs, run.clusters, run.visAttrs, buffer.ptr); + run.glyphCount = buffer[0]; + } + int[3] abc; run.advances = cast(int*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, run.glyphCount * 4); if (run.advances is null) DWT.error(DWT.ERROR_NO_HANDLES); run.goffsets = cast(GOFFSET*)OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, run.glyphCount * GOFFSET_SIZEOF); if (run.goffsets is null) DWT.error(DWT.ERROR_NO_HANDLES); - OS.ScriptPlace(hdc, run.psc, run.glyphs, run.glyphCount, run.visAttrs, &run.analysis, run.advances, run.goffsets, &abc); - if (run.style !is null && run.style.metrics !is null) { - GlyphMetrics metrics = run.style.metrics; - /* - * Bug in Windows, on a Japanese machine, Uniscribe returns glyphcount - * equals zero for FFFC (possibly other unicode code points), the fix - * is to make sure the glyph is at least one pixel wide. - */ - run.width = metrics.width * Math.max (1, run.glyphCount); - run.ascent = metrics.ascent; - run.descent = metrics.descent; - run.leading = 0; + OS.ScriptPlace(hdc, run.psc, run.glyphs, run.glyphCount, run.visAttrs, &run.analysis, run.advances, run.goffsets, cast(ABC*)abc.ptr); + run.width = abc[0] + abc[1] + abc[2]; + TextStyle style = run.style; + if (style !is null) { + OUTLINETEXTMETRIC* lotm = null; + if (style.underline || style.strikeout) { + lotm = new OUTLINETEXTMETRIC(); + if (OS.GetOutlineTextMetrics(hdc, OUTLINETEXTMETRIC.sizeof, lotm) is 0) { + lotm = null; + } + } + if (style.metrics !is null) { + GlyphMetrics metrics = style.metrics; + /* + * Bug in Windows, on a Japanese machine, Uniscribe returns glyphcount + * equals zero for FFFC (possibly other unicode code points), the fix + * is to make sure the glyph is at least one pixel wide. + */ + run.width = metrics.width * Math.max (1, run.glyphCount); + run.ascent = metrics.ascent; + run.descent = metrics.descent; + run.leading = 0; + } else { + TEXTMETRIC lptm; + if (lotm !is null) { + lptm = lotm.otmTextMetrics; + } else { + lptm = TEXTMETRIC.init; + OS.GetTextMetrics(hdc, &lptm); + } + run.ascent = lptm.tmAscent; + run.descent = lptm.tmDescent; + run.leading = lptm.tmInternalLeading; + } + if (lotm !is null) { + run.underlinePos = lotm.otmsUnderscorePosition; + run.underlineThickness = Math.max(1, lotm.otmsUnderscoreSize); + run.strikeoutPos = lotm.otmsStrikeoutPosition; + run.strikeoutThickness = Math.max(1, lotm.otmsStrikeoutSize); + } else { + run.underlinePos = 1; + run.underlineThickness = 1; + run.strikeoutPos = run.ascent / 2; + run.strikeoutThickness = 1; + } + run.ascent += style.rise; + run.descent -= style.rise; } else { - run.width = abc.abcA + abc.abcB + abc.abcC; TEXTMETRIC lptm; OS.GetTextMetrics(hdc, &lptm); run.ascent = lptm.tmAscent; run.descent = lptm.tmDescent; run.leading = lptm.tmInternalLeading; } - if (run.style !is null) { - run.ascent += run.style.rise; - run.descent -= +run.style.rise; - } } int validadeOffset(int offset, int step) { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/TextStyle.d --- a/dwt/graphics/TextStyle.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/TextStyle.d Sat May 17 17:34:28 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2006 IBM Corporation and others. + * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -59,13 +59,40 @@ public Color background; /** - * the underline flag of the style + * the underline flag of the style. The default underline + * style is DWT.UNDERLINE_SINGLE. + * * * @since 3.1 */ public bool underline; /** + * the underline color of the style + * + * @since 3.4 + */ + public Color underlineColor; + + /** + * the underline style. This style is ignored when + * underline is false. + *

    + * This value should be one of DWT.UNDERLINE_SINGLE, + * DWT.UNDERLINE_DOUBLE, DWT.UNDERLINE_ERROR, + * or DWT.UNDERLINE_SQUIGGLE. + *

    + * + * @see DWT#UNDERLINE_SINGLE + * @see DWT#UNDERLINE_DOUBLE + * @see DWT#UNDERLINE_ERROR + * @see DWT#UNDERLINE_SQUIGGLE + * + * @since 3.4 + */ + public int underlineStyle; + + /** * the strikeout flag of the style * * @since 3.1 @@ -73,6 +100,37 @@ public bool strikeout; /** + * the strikeout color of the style + * + * @since 3.4 + */ + public Color strikeoutColor; + + /** + * the border style. The default border style is DWT.NONE. + *

    + * This value should be one of DWT.BORDER_SOLID, + * DWT.BORDER_DASH,DWT.BORDER_DOT or + * DWT.NONE. + *

    + * + * @see DWT#BORDER_SOLID + * @see DWT#BORDER_DASH + * @see DWT#BORDER_DOT + * @see DWT#NONE + * + * @since 3.4 + */ + public int borderStyle; + + /** + * the border color of the style + * + * @since 3.4 + */ + public Color borderColor; + + /** * the GlyphMetrics of the style * * @since 3.2 @@ -86,17 +144,12 @@ */ public int rise; -/++ - + DWT extension for clone implementation - +/ -protected this( TextStyle other ){ - font = other.font; - foreground = other.foreground; - background = other.background; - underline = other.underline; - strikeout = other.strikeout; - metrics = other.metrics; - rise = other.rise; +/** + * Create an empty text style. + * + * @since 3.4 + */ +public this () { } /** @@ -116,6 +169,30 @@ this.background = background; } + +/** + * Create a new text style from an existing text style. + * + *@param style the style to copy + * + * @since 3.4 + */ +public this (TextStyle style) { + if (style is null) DWT.error (DWT.ERROR_INVALID_ARGUMENT); + font = style.font; + foreground = style.foreground; + background = style.background; + underline = style.underline; + underlineColor = style.underlineColor; + underlineStyle = style.underlineStyle; + strikeout = style.strikeout; + strikeoutColor = style.strikeoutColor; + borderStyle = style.borderStyle; + borderColor = style.borderColor; + metrics = style.metrics; + rise = style.rise; +} + /** * Compares the argument to the receiver, and returns true * if they represent the same object using a class @@ -142,8 +219,20 @@ } else if (style.font !is null) return false; if (metrics !is null || style.metrics !is null) return false; if (underline !is style.underline) return false; + if (underlineStyle !is style.underlineStyle) return false; + if (borderStyle !is style.borderStyle) return false; if (strikeout !is style.strikeout) return false; if (rise !is style.rise) return false; + if (underlineColor !is null) { + if (!underlineColor.equals(style.underlineColor)) return false; + } else if (style.underlineColor !is null) return false; + if (strikeoutColor !is null) { + if (!strikeoutColor.equals(style.strikeoutColor)) return false; + } else if (style.strikeoutColor !is null) return false; + if (underlineStyle !is style.underlineStyle) return false; + if (borderColor !is null) { + if (!borderColor.equals(style.borderColor)) return false; + } else if (style.borderColor !is null) return false; return true; } @@ -166,9 +255,44 @@ if (underline) hash ^= hash; if (strikeout) hash ^= hash; hash ^= rise; + if (underlineColor !is null) hash ^= underlineColor.hashCode(); + if (strikeoutColor !is null) hash ^= strikeoutColor.hashCode(); + if (borderColor !is null) hash ^= borderColor.hashCode(); + hash ^= underlineStyle; return hash; } +bool isAdherentBorder(TextStyle style) { + if (this is style) return true; + if (style is null) return false; + if (borderStyle !is style.borderStyle) return false; + if (borderColor !is null) { + if (!borderColor.equals(style.borderColor)) return false; + } else if (style.borderColor !is null) return false; + return true; +} + +bool isAdherentUnderline(TextStyle style) { + if (this is style) return true; + if (style is null) return false; + if (underline !is style.underline) return false; + if (underlineStyle !is style.underlineStyle) return false; + if (underlineColor !is null) { + if (!underlineColor.equals(style.underlineColor)) return false; + } else if (style.underlineColor !is null) return false; + return true; +} + +bool isAdherentStrikeout(TextStyle style) { + if (this is style) return true; + if (style is null) return false; + if (strikeout !is style.strikeout) return false; + if (strikeoutColor !is null) { + if (!strikeoutColor.equals(style.strikeoutColor)) return false; + } else if (style.strikeoutColor !is null) return false; + return true; +} + /** * Returns a string containing a concise, human-readable * description of the receiver. diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/graphics/Transform.d --- a/dwt/graphics/Transform.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/graphics/Transform.d Sat May 17 17:34:28 2008 +0200 @@ -39,7 +39,7 @@ * @since 3.1 */ public class Transform : Resource { - + alias Resource.init_ init_; /** * the OS resource for the Transform * (Warning: This field is platform dependent) @@ -137,13 +137,11 @@ * @see #dispose() */ public this (Device device, float m11, float m12, float m21, float m22, float dx, float dy) { - if (device is null) device = Device.getDevice(); - if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - this.device = device; - device.checkGDIP(); + super(device); + this.device.checkGDIP(); handle = Gdip.Matrix_new(m11, m12, m21, m22, dx, dy); if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES); - if (device.tracking) device.new_Object(this); + init_(); } static float[] checkTransform(float[] elements) { @@ -152,18 +150,9 @@ return elements; } -/** - * Disposes of the operating system resources associated with - * the Transform. Applications must dispose of all Transforms that - * they allocate. - */ -override public void dispose() { - if (handle is null) return; - if (device.isDisposed()) return; +void destroy() { Gdip.Matrix_delete(handle); handle = null; - if (device.tracking) device.dispose_Object(this); - device = null; } /** @@ -184,11 +173,26 @@ if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); if (elements is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); if (elements.length < 6) DWT.error(DWT.ERROR_INVALID_ARGUMENT); - Gdip.Matrix_GetElements(handle, elements); + Gdip.Matrix_GetElements(handle, elements.ptr); } /** * Modifies the receiver such that the matrix it represents becomes the + * identity matrix. + * + * @exception DWTException
      + *
    • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.4 + */ +public void identity() { + if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + Gdip.Matrix_SetElements(handle, 1, 0, 0, 1, 0, 0); +} + +/** + * Modifies the receiver such that the matrix it represents becomes * the mathematical inverse of the matrix it previously represented. * * @exception DWTException
      @@ -303,6 +307,24 @@ } /** + * Modifies the receiver so that it represents a transformation that is + * equivalent to its previous transformation sheared by (shearX, shearY). + * + * @param shearX the shear factor in the X direction + * @param shearY the shear factor in the Y direction + * + * @exception DWTException
        + *
      • ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed
      • + *
      + * + * @since 3.4 + */ +public void shear(float shearX, float shearY) { + if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + Gdip.Matrix_Shear(handle, shearX, shearY, Gdip.MatrixOrderPrepend); +} + +/** * Given an array containing points described by alternating x and y values, * modify that array such that each point has been replaced with the result of * applying the transformation represented by the receiver to that point. @@ -319,7 +341,7 @@ public void transform(float[] pointArray) { if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); if (pointArray is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); - Gdip.Matrix_TransformPoints(handle, cast(Gdip.PointF[])pointArray, pointArray.length / 2); + Gdip.Matrix_TransformPoints(handle, cast(Gdip.PointF*)pointArray.ptr, pointArray.length / 2); } /** diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/BidiUtil.d --- a/dwt/internal/BidiUtil.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/BidiUtil.d Sat May 17 17:34:28 2008 +0200 @@ -17,6 +17,7 @@ import dwt.graphics.GC; import dwt.internal.win32.OS; +import dwt.widgets.Control; import tango.util.Convert; import dwt.dwthelper.utils; import dwt.dwthelper.Runnable; @@ -112,6 +113,9 @@ languageMap[hwnd] = runnable; subclass(hwnd); } +public static void addLanguageListener (Control control, Runnable runnable) { + addLanguageListener(control.handle, runnable); +} /** * Proc used for OS.EnumSystemLanguageGroups call during isBidiPlatform test. */ @@ -407,11 +411,9 @@ */ public static int getKeyboardLanguage() { int layout = cast(int) OS.GetKeyboardLayout(0); - // only interested in low 2 bytes, which is the primary - // language identifier - layout = layout & 0x000000FF; - if (layout is LANG_HEBREW) return KEYBOARD_BIDI; - if (layout is LANG_ARABIC) return KEYBOARD_BIDI; + int langID = OS.PRIMARYLANGID(OS.LOWORD(layout)); + if (langID is LANG_HEBREW) return KEYBOARD_BIDI; + if (langID is LANG_ARABIC) return KEYBOARD_BIDI; // return non-bidi for all other languages return KEYBOARD_NON_BIDI; } @@ -482,7 +484,7 @@ public static bool isKeyboardBidi() { void*[] list = getKeyboardLanguageList(); for (int i=0; inull + * @exception IOException + * + * @since 3.4 + */ +public static OutputStream newDeflaterOutputStream(OutputStream stream) { + //DWT_TODO + implMissing(__FILE__,__LINE__); + return null; + //return new DeflaterOutputStream(stream); +} + +/** * Open a file if such things are supported. * * @param filename the name of the file to open diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/ImageList.d --- a/dwt/internal/ImageList.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/ImageList.d Sat May 17 17:34:28 2008 +0200 @@ -138,8 +138,8 @@ bmi[offset + 10] = cast(byte)((blueMask & 0xFF00) >> 8); bmi[offset + 11] = cast(byte)((blueMask & 0xFF) >> 0); } - int[1] pBits; - hBitmap = OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0); + void* pBits; + hBitmap = OS.CreateDIBSection(null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0); } else { hBitmap = OS.CreateCompatibleBitmap (hDC, width, height); } @@ -183,8 +183,8 @@ byte [] bmi = new byte[BITMAPINFOHEADER.sizeof]; *cast(BITMAPINFOHEADER*)bmi.ptr = bmiHeader; //OS.MoveMemory (bmi, bmiHeader, BITMAPINFOHEADER.sizeof); - int [1] pBits; - auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, pBits.ptr, null, 0); + void* pBits; + auto memDib = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi.ptr, OS.DIB_RGB_COLORS, &pBits, null, 0); if (memDib is null) DWT.error (DWT.ERROR_NO_HANDLES); auto oldMemBitmap = OS.SelectObject (memHdc, memDib); @@ -237,8 +237,8 @@ byte [] bmi2 = new byte[BITMAPINFOHEADER.sizeof]; *cast(BITMAPINFOHEADER*)bmi2.ptr = bmiHeader2; //OS.MoveMemory (bmi2, bmiHeader2, BITMAPINFOHEADER.sizeof); - int [1] pBits2; - auto memDib2 = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi2.ptr, OS.DIB_RGB_COLORS, pBits2.ptr, null, 0); + void* pBits2; + auto memDib2 = OS.CreateDIBSection (null, cast(BITMAPINFO*)bmi2.ptr, OS.DIB_RGB_COLORS, &pBits2, null, 0); auto memHdc2 = OS.CreateCompatibleDC (hdc); auto oldMemBitmap2 = OS.SelectObject (memHdc2, memDib2); static if (!OS.IsWinCE) OS.SetStretchBltMode(memHdc2, OS.COLORONCOLOR); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/Library.d --- a/dwt/internal/Library.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/Library.d Sat May 17 17:34:28 2008 +0200 @@ -34,7 +34,7 @@ /** * DWT Minor version number (must be in the range 0..999) */ - static const int MINOR_VERSION = 349; + static const int MINOR_VERSION = 442; /** * DWT revision number (must be >= 0) @@ -178,6 +178,20 @@ * @param mapName true if the name should be mapped, false otherwise */ public static void loadLibrary (String name, boolean mapName) { + String prop = System.getProperty ("sun.arch.data.model"); //$NON-NLS-1$ + if (prop is null) prop = System.getProperty ("com.ibm.vm.bitmode"); //$NON-NLS-1$ + if (prop !is null) { + if ("32".equals (prop)) { //$NON-NLS-1$ + if (0x1FFFFFFFFL is (int /*long*/)0x1FFFFFFFFL) { + throw new UnsatisfiedLinkError ("Cannot load 64-bit DWT libraries on 32-bit JVM"); //$NON-NLS-1$ + } + } + if ("64".equals (prop)) { //$NON-NLS-1$ + if (0x1FFFFFFFFL !is (int /*long*/)0x1FFFFFFFFL) { + throw new UnsatisfiedLinkError ("Cannot load 32-bit DWT libraries on 64-bit JVM"); //$NON-NLS-1$ + } + } + } /* Compute the library name and mapped name */ String libName1, libName2, mappedName1, mappedName2; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/gdip/Gdip.d --- a/dwt/internal/gdip/Gdip.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/gdip/Gdip.d Sat May 17 17:34:28 2008 +0200 @@ -791,13 +791,13 @@ **************************************************************************/ static Status LinearGradientBrush_SetInterpolationColors( LinearGradientBrush brush, - ARGB[] presetColors, float[] blendPositions, int count ) + ARGB* presetColors, float* blendPositions, int count ) { if ((count <= 0) || presetColors is null) return SetStatus(Status.InvalidParameter); - return SetStatus(GdipSetLinePresetBlend(brush, presetColors.ptr, - blendPositions.ptr, + return SetStatus(GdipSetLinePresetBlend(brush, presetColors, + blendPositions, count ) ); } @@ -1004,9 +1004,9 @@ **************************************************************************/ - static Status Pen_SetDashPattern( Pen pen, float[] dashArray, int count ) + static Status Pen_SetDashPattern( Pen pen, float* dashArray, int count ) { - return SetStatus(GdipSetPenDashArray(pen, dashArray.ptr, count)); + return SetStatus(GdipSetPenDashArray(pen, dashArray, count)); } /************************************************************************** @@ -1276,11 +1276,11 @@ **************************************************************************/ - static Path GraphicsPath_new( Point[] points, ubyte[] types, int count, + static Path GraphicsPath_new( Point* points, ubyte* types, int count, FillMode fillMode = FillModeAlternate ) { Path path = null; - lastResult = GdipCreatePath2I(points.ptr, types.ptr, count, fillMode, path); + lastResult = GdipCreatePath2I(points, types, count, fillMode, path); return path; } @@ -1292,6 +1292,11 @@ { GdipDeletePath(path); } + static Path GraphicsPath_Clone( Handle path ){ + Path clonepath = null; + SetStatus( GdipClonePath(path, clonepath)); + return clonepath; + } static Status GraphicsPath_AddArcF( Path path, float x, float y, @@ -1427,18 +1432,18 @@ **************************************************************************/ - static Status GraphicsPath_GetPathTypes( Path path, byte[] types, int count ) + static Status GraphicsPath_GetPathTypes( Path path, byte* types, int count ) { - return SetStatus( GdipGetPathTypes( path, types.ptr, count) ); + return SetStatus( GdipGetPathTypes( path, types, count) ); } /************************************************************************** **************************************************************************/ - static Status GraphicsPath_GetPathPoints( Path path, PointF[] points, int count) + static Status GraphicsPath_GetPathPoints( Path path, PointF* points, int count) { - return SetStatus(GdipGetPathPoints(path, points.ptr, count)); + return SetStatus(GdipGetPathPoints(path, points, count)); } @@ -1605,9 +1610,9 @@ **************************************************************************/ - static Status Graphics_DrawLines( Graphics graphics, Pen pen, Point[] points, uint count ) + static Status Graphics_DrawLines( Graphics graphics, Pen pen, Point* points, uint count ) { - return SetStatus(GdipDrawLinesI(graphics, pen, points.ptr, count)); + return SetStatus(GdipDrawLinesI(graphics, pen, points, count)); } /************************************************************************** @@ -1623,9 +1628,9 @@ **************************************************************************/ - static Status Graphics_DrawPolygon(Graphics graphics, Pen pen, Point[] points, uint count ) + static Status Graphics_DrawPolygon(Graphics graphics, Pen pen, Point* points, uint count ) { - return SetStatus(GdipDrawPolygonI(graphics, pen, points.ptr, count)); + return SetStatus(GdipDrawPolygonI(graphics, pen, points, count)); } @@ -1712,9 +1717,9 @@ **************************************************************************/ static Status Graphics_FillPolygon( Graphics graphics, Brush brush, - Point[] points, int count, FillMode fillMode ) + Point* points, int count, FillMode fillMode ) { - return SetStatus(GdipFillPolygonI(graphics, brush, points.ptr, count, fillMode)); + return SetStatus(GdipFillPolygonI(graphics, brush, points, count, fillMode)); } /************************************************************************** @@ -1938,7 +1943,7 @@ **************************************************************************/ - static Status Graphics_SetClip( Graphics graphics, Path path, + static Status Graphics_SetClipPath( Graphics graphics, Path path, CombineMode combineMode = CombineModeReplace ) { return SetStatus(GdipSetClipPath(graphics, path, combineMode)); @@ -1957,6 +1962,9 @@ combineMode)); } + //static Status Graphics_SetClipPath(Graphics graphics, GraphicsPath path ){ + // return SetStatus( SetClipPath( graphics, path )); + //} /************************************************************************** **************************************************************************/ @@ -2125,9 +2133,9 @@ **************************************************************************/ - static Status Matrix_GetElements( Matrix matrix, float[] m ) + static Status Matrix_GetElements( Matrix matrix, float* m ) { - return SetStatus( GdipGetMatrixElements( matrix, m.ptr ) ); + return SetStatus( GdipGetMatrixElements( matrix, m ) ); } /************************************************************************** @@ -2180,6 +2188,9 @@ { return SetStatus( GdipScaleMatrix(matrix, scaleX, scaleY, order) ); } + static Status Matrix_Shear( Matrix matrix, float shearX, float shearY, MatrixOrder order ){ + return SetStatus( GdipShearMatrix(matrix, shearX, shearY, order)); + } /************************************************************************** @@ -2196,9 +2207,9 @@ **************************************************************************/ - static Status Matrix_TransformPoints( Matrix matrix, PointF[] pts, int count = 1 ) + static Status Matrix_TransformPoints( Matrix matrix, PointF* pts, int count = 1 ) { - return SetStatus( GdipTransformMatrixPoints( matrix, pts.ptr, count ) ); + return SetStatus( GdipTransformMatrixPoints( matrix, pts, count ) ); } /************************************************************************** @@ -2310,10 +2321,10 @@ **************************************************************************/ static int StringFormat_SetTabStops( StringFormat format, float firstTabOffset, - int count, float[] tabStops) + int count, float* tabStops) { return SetStatus( GdipSetStringFormatTabStops( format, firstTabOffset, - count, tabStops.ptr ) ); + count, tabStops ) ); } /************************************************************************** diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/FileFormat.d --- a/dwt/internal/image/FileFormat.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/FileFormat.d Sat May 17 17:34:28 2008 +0200 @@ -12,6 +12,8 @@ *******************************************************************************/ module dwt.internal.image.FileFormat; +import dwt.dwthelper.utils; + public import dwt.graphics.ImageLoader; public import dwt.graphics.ImageData; public import dwt.internal.image.LEDataInputStream; @@ -32,7 +34,6 @@ import tango.core.Exception; import tango.core.Tuple; -import dwt.dwthelper.utils; /** * Abstract factory class for loading/unloading images from files or streams @@ -81,7 +82,7 @@ public static ImageData[] load(InputStream istr, ImageLoader loader) { FileFormat fileFormat = null; LEDataInputStream stream = new LEDataInputStream(istr); - bool isSupported = false; + bool isSupported = false; foreach( TFormat; TFormats ){ try{ fileFormat = new TFormat(); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/GIFFileFormat.d --- a/dwt/internal/image/GIFFileFormat.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/GIFFileFormat.d Sat May 17 17:34:28 2008 +0200 @@ -22,9 +22,9 @@ import dwt.graphics.ImageLoaderEvent; import dwt.graphics.ImageLoader; import tango.core.Exception; -import dwt.dwthelper.System; import dwt.dwthelper.utils; + final class GIFFileFormat : FileFormat { String signature; int screenWidth, screenHeight, backgroundPixel, bitsPerPixel, defaultDepth; @@ -62,7 +62,7 @@ byte[3] signature; stream.read(signature); stream.unread(signature); - return cast(String)signature == "GIF"; //$NON-NLS-1$ + return signature[0] is 'G' && signature[1] is 'I' && signature[2] is 'F'; } catch (Exception e) { return false; } @@ -73,13 +73,12 @@ * Return an array of ImageData representing the image(s). */ override ImageData[] loadFromByteStream() { - byte[3] signatureBytes; + byte[3] signature; byte[3] versionBytes; byte[7] block; try { - inputStream.read(signatureBytes); - signature = cast(String)signatureBytes.dup; - if (signature != "GIF") //$NON-NLS-1$ + inputStream.read(signature); + if (!(signature[0] is 'G' && signature[1] is 'I' && signature[2] is 'F')) DWT.error(DWT.ERROR_INVALID_IMAGE); inputStream.read(versionBytes); @@ -313,13 +312,11 @@ // Read size of block = 0x0B. inputStream.read(); // Read application identifier. - byte[] applicationBytes = new byte[8]; - inputStream.read(applicationBytes); - String application = cast(String)(applicationBytes.dup); + byte[] application = new byte[8]; + inputStream.read(application); // Read authentication code. - byte[] authenticationBytes = new byte[3]; - inputStream.read(authenticationBytes); - String authentication = cast(String)(authenticationBytes.dup); + byte[] authentication = new byte[3]; + inputStream.read(authentication); // Read application data. byte[] data = new byte[0]; byte[] block = new byte[255]; @@ -333,7 +330,20 @@ size = inputStream.read(); } // Look for the NETSCAPE 'repeat count' field for an animated GIF. - if (application=="NETSCAPE" && authentication=="2.0" && data[0] is 01) { //$NON-NLS-1$ //$NON-NLS-2$ + bool netscape = + application[0] is 'N' && + application[1] is 'E' && + application[2] is 'T' && + application[3] is 'S' && + application[4] is 'C' && + application[5] is 'A' && + application[6] is 'P' && + application[7] is 'E'; + bool authentic = + authentication[0] is '2' && + authentication[1] is '.' && + authentication[2] is '0'; + if (netscape && authentic && data[0] is 01) { //$NON-NLS-1$ //$NON-NLS-2$ repeatCount = (data[1] & 0xFF) | ((data[2] & 0xFF) << 8); loader.repeatCount = repeatCount; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGAppn.d --- a/dwt/internal/image/JPEGAppn.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGAppn.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -26,7 +26,7 @@ super(byteStream); } - override public bool verify() { + public override bool verify() { int marker = getSegmentMarker(); return marker >= JPEGFileFormat.APP0 && marker <= JPEGFileFormat.APP15; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGArithmeticConditioningTable.d --- a/dwt/internal/image/JPEGArithmeticConditioningTable.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGArithmeticConditioningTable.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -22,7 +22,7 @@ super(byteStream); } - override public int signature() { + public override int signature() { return JPEGFileFormat.DAC; } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGComment.d --- a/dwt/internal/image/JPEGComment.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGComment.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -26,7 +26,7 @@ super(byteStream); } - override public int signature() { + public override int signature() { return JPEGFileFormat.COM; } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGDecoder.d --- a/dwt/internal/image/JPEGDecoder.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGDecoder.d Sat May 17 17:34:28 2008 +0200 @@ -20,12 +20,11 @@ import dwt.graphics.ImageLoaderEvent; import dwt.graphics.PaletteData; import dwt.graphics.RGB; +import dwt.dwthelper.utils; import tango.core.Exception; import tango.util.Convert; import Math = tango.math.Math; -import dwt.dwthelper.System; -import dwt.dwthelper.utils; public class JPEGDecoder { @@ -980,7 +979,7 @@ r = s >> 4; s &= 15; if (s !is 0) { - if (s !is 1) { /* size of new coef should always be 1 */ + if (s !is 1) { /* size of new coef should always be 1 */ // WARNMS(cinfo, JWRN_HUFF_BAD_CODE); } // CHECK_BIT_BUFFER(br_state, 1, goto undoit); @@ -1243,7 +1242,7 @@ k += 15; /* skip 15 zeroes in band */ } else { /* EOBr, run length is 2^r + appended bits */ EOBRUN = 1 << r; - if (r !is 0) { /* EOBr, r > 0 */ + if (r !is 0) { /* EOBr, r > 0 */ // CHECK_BIT_BUFFER(br_state, r, return FALSE); { if (bits_left < (r)) { @@ -1281,7 +1280,7 @@ return true; } - bool decode_mcu_DC_first (jpeg_decompress_struct cinfo, short[][] MCU_data) { + bool decode_mcu_DC_first (jpeg_decompress_struct cinfo, short[][] MCU_data) { phuff_entropy_decoder entropy = this; int Al = cinfo.Al; int s = 0, r; @@ -1645,7 +1644,7 @@ /* Variables for Floyd-Steinberg dithering */ // FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ - bool on_odd_row; + bool on_odd_row; void start_pass (jpeg_decompress_struct cinfo, bool is_pre_scan) { error(); @@ -4449,7 +4448,7 @@ length -= count; - if ((index & 0x10) !is 0) { /* AC table definition */ + if ((index & 0x10) !is 0) { /* AC table definition */ index -= 0x10; htblptr = cinfo.ac_huff_tbl_ptrs[index] = new JHUFF_TBL(); } else { /* DC table definition */ @@ -5238,7 +5237,7 @@ // GETJOCTET(data[12]), GETJOCTET(data[13])); } totallen -= APP0_DATA_LEN; - if (totallen !is ((data[12] & 0xFF) * (data[13] & 0xFF) * 3)) { + if (totallen !is ((data[12] & 0xFF) * (data[13] & 0xFF) * 3)) { // TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, cast(int) totallen); } } else if (datalen >= 6 && diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGEndOfImage.d --- a/dwt/internal/image/JPEGEndOfImage.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGEndOfImage.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -26,11 +26,11 @@ super(reference); } - override public int signature() { + public override int signature() { return JPEGFileFormat.EOI; } - override public int fixedSize() { + public override int fixedSize() { return 2; } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGFileFormat.d --- a/dwt/internal/image/JPEGFileFormat.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGFileFormat.d Sat May 17 17:34:28 2008 +0200 @@ -25,10 +25,10 @@ import dwt.internal.image.JPEGStartOfImage; import dwt.internal.image.JPEGDecoder; import dwt.internal.image.JPEGEndOfImage; +import dwt.dwthelper.utils; import dwt.graphics.RGB; import dwt.graphics.PaletteData; -import dwt.dwthelper.System; import tango.core.Exception; @@ -150,39 +150,87 @@ public static int[] CrRTable, CbBTable, CrGTable, CbGTable; public static int[] RYTable, GYTable, BYTable, RCbTable, GCbTable, BCbTable, RCrTable, GCrTable, BCrTable, NBitsTable; + //public static void static_this() { + static this() { - private static bool static_this_completed = false; - private static void static_this() { - if( static_this_completed ){ - return; + RGB16 = [ + new RGB(0,0,0), + new RGB(0x80,0,0), + new RGB(0,0x80,0), + new RGB(0x80,0x80,0), + new RGB(0,0,0x80), + new RGB(0x80,0,0x80), + new RGB(0,0x80,0x80), + new RGB(0xC0,0xC0,0xC0), + new RGB(0x80,0x80,0x80), + new RGB(0xFF,0,0), + new RGB(0,0xFF,0), + new RGB(0xFF,0xFF,0), + new RGB(0,0,0xFF), + new RGB(0xFF,0,0xFF), + new RGB(0,0xFF,0xFF), + new RGB(0xFF,0xFF,0xFF) + ]; + int [] rYTable = new int[256]; + int [] gYTable = new int[256]; + int [] bYTable = new int[256]; + int [] rCbTable = new int[256]; + int [] gCbTable = new int[256]; + int [] bCbTable = new int[256]; + int [] rCrTable = new int[256]; + int [] gCrTable = new int[256]; + int [] bCrTable = new int[256]; + for (int i = 0; i < 256; i++) { + rYTable[i] = i * 19595; + gYTable[i] = i * 38470; + bYTable[i] = i * 7471 + 32768; + rCbTable[i] = i * -11059; + gCbTable[i] = i * -21709; + bCbTable[i] = i * 32768 + 8388608; + gCrTable[i] = i * -27439; + bCrTable[i] = i * -5329; } - synchronized { - if( static_this_completed ){ - return; + RYTable = rYTable; + GYTable = gYTable; + BYTable = bYTable; + RCbTable = rCbTable; + GCbTable = gCbTable; + BCbTable = bCbTable; + RCrTable = bCbTable; + GCrTable = gCrTable; + BCrTable = bCrTable; + + /* Initialize YCbCr-RGB Tables */ + int [] crRTable = new int[256]; + int [] cbBTable = new int[256]; + int [] crGTable = new int[256]; + int [] cbGTable = new int[256]; + for (int i = 0; i < 256; i++) { + int x2 = 2 * i - 255; + crRTable[i] = (45941 * x2 + 32768) >> 16; + cbBTable[i] = (58065 * x2 + 32768) >> 16; + crGTable[i] = -23401 * x2; + cbGTable[i] = -11277 * x2 + 32768; + } + CrRTable = crRTable; + CbBTable = cbBTable; + CrGTable = crGTable; + CbGTable = cbGTable; + + /* Initialize BitCount Table */ + int nBits = 1; + int power2 = 2; + int [] nBitsTable = new int[2048]; + nBitsTable[0] = 0; + for (int i = 1; i < nBitsTable.length; i++) { + if (!(i < power2)) { + nBits++; + power2 *= 2; } - initialize(); - RGB16 = [ - new RGB(0,0,0), - new RGB(0x80,0,0), - new RGB(0,0x80,0), - new RGB(0x80,0x80,0), - new RGB(0,0,0x80), - new RGB(0x80,0,0x80), - new RGB(0,0x80,0x80), - new RGB(0xC0,0xC0,0xC0), - new RGB(0x80,0x80,0x80), - new RGB(0xFF,0,0), - new RGB(0,0xFF,0), - new RGB(0xFF,0xFF,0), - new RGB(0,0,0xFF), - new RGB(0xFF,0,0xFF), - new RGB(0,0xFF,0xFF), - new RGB(0xFF,0xFF,0xFF) - ]; - static_this_completed = true; + nBitsTable[i] = nBits; } + NBitsTable = nBitsTable; } - void compress(ImageData image, byte[] dataYComp, byte[] dataCbComp, byte[] dataCrComp) { int srcWidth = image.width; int srcHeight = image.height; @@ -240,15 +288,15 @@ int delta = componentWidth - compressedWidth; for (int yPos = 0; yPos < compressedHeight; yPos++) { int dstOfs = ((yPos + 1) * componentWidth - delta); - int dataValue = imageComponent[dstOfs - 1] & 0xFF; + int dataValue = imageComponent[(dstOfs > 0) ? dstOfs - 1 : 0] & 0xFF; for (int i = 0; i < delta; i++) { imageComponent[dstOfs + i] = cast(byte)dataValue; } } } if (compressedHeight < componentHeight) { - int srcOfs = (compressedHeight - 1) * componentWidth; - for (int yPos = compressedHeight; yPos <= componentHeight; yPos++) { + int srcOfs = (compressedHeight > 0) ? (compressedHeight - 1) * componentWidth : 1; + for (int yPos = (compressedHeight > 0) ? compressedHeight : 1; yPos <= componentHeight; yPos++) { int dstOfs = (yPos - 1) * componentWidth; System.arraycopy(imageComponent, srcOfs, imageComponent, dstOfs, componentWidth); } @@ -1171,58 +1219,6 @@ } restartInterval = dri.getRestartInterval(); } -static void initialize() { - initializeRGBYCbCrTables(); - initializeYCbCrRGBTables(); - initializeBitCountTable(); -} -static void initializeBitCountTable() { - int nBits = 1; - int power2 = 2; - NBitsTable = new int[2048]; - NBitsTable[0] = 0; - for (int i = 1; i < NBitsTable.length; i++) { - if (!(i < power2)) { - nBits++; - power2 *= 2; - } - NBitsTable[i] = nBits; - } -} -static void initializeRGBYCbCrTables() { - RYTable = new int[256]; - GYTable = new int[256]; - BYTable = new int[256]; - RCbTable = new int[256]; - GCbTable = new int[256]; - BCbTable = new int[256]; - RCrTable = BCbTable; - GCrTable = new int[256]; - BCrTable = new int[256]; - for (int i = 0; i < 256; i++) { - RYTable[i] = i * 19595; - GYTable[i] = i * 38470; - BYTable[i] = i * 7471 + 32768; - RCbTable[i] = i * -11059; - GCbTable[i] = i * -21709; - BCbTable[i] = i * 32768 + 8388608; - GCrTable[i] = i * -27439; - BCrTable[i] = i * -5329; - } -} -static void initializeYCbCrRGBTables() { - CrRTable = new int[256]; - CbBTable = new int[256]; - CrGTable = new int[256]; - CbGTable = new int[256]; - for (int i = 0; i < 256; i++) { - int x2 = 2 * i - 255; - CrRTable[i] = (45941 * x2 + 32768) >> 16; - CbBTable[i] = (58065 * x2 + 32768) >> 16; - CrGTable[i] = -23401 * x2; - CbGTable[i] = -11277 * x2 + 32768; - } -} void inverseDCT(int[] dataUnit) { for (int row = 0; row < 8; row++) { int rIndex = row * DCTSIZE; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGFixedSizeSegment.d --- a/dwt/internal/image/JPEGFixedSizeSegment.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGFixedSizeSegment.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -42,10 +42,10 @@ abstract public int fixedSize(); - override public int getSegmentLength() { + public override int getSegmentLength() { return fixedSize() - 2; } - override public void setSegmentLength(int length) { + public override void setSegmentLength(int length) { } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGFrameHeader.d --- a/dwt/internal/image/JPEGFrameHeader.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGFrameHeader.d Sat May 17 17:34:28 2008 +0200 @@ -17,7 +17,7 @@ import dwt.internal.image.JPEGVariableSizeSegment; import dwt.internal.image.JPEGFileFormat; import dwt.internal.image.LEDataInputStream; -import dwt.dwthelper.System; +import dwt.dwthelper.utils; final class JPEGFrameHeader : JPEGVariableSizeSegment { int maxVFactor; @@ -198,7 +198,7 @@ * SOF_14 - Differential progressive, arithmetic coding * SOF_15 - Differential lossless, arithmetic coding */ - override public bool verify() { + public override bool verify() { int marker = getSegmentMarker(); return (marker >= JPEGFileFormat.SOF0 && marker <= JPEGFileFormat.SOF3) || (marker >= JPEGFileFormat.SOF5 && marker <= JPEGFileFormat.SOF7) || diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGHuffmanTable.d --- a/dwt/internal/image/JPEGHuffmanTable.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGHuffmanTable.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -264,7 +264,7 @@ System.arraycopy(huffTables, 0, allTables, 0, huffTableCount); } -override public int signature() { +public override int signature() { return JPEGFileFormat.DHT; } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGQuantizationTable.d --- a/dwt/internal/image/JPEGQuantizationTable.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGQuantizationTable.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -166,7 +166,7 @@ } } -override public int signature() { +public override int signature() { return JPEGFileFormat.DQT; } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGRestartInterval.d --- a/dwt/internal/image/JPEGRestartInterval.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGRestartInterval.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -22,7 +22,7 @@ super(byteStream); } - override public int signature() { + public override int signature() { return JPEGFileFormat.DRI; } @@ -30,7 +30,7 @@ return ((reference[4] & 0xFF) << 8 | (reference[5] & 0xFF)); } - override public int fixedSize() { + public override int fixedSize() { return 6; } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGScanHeader.d --- a/dwt/internal/image/JPEGScanHeader.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGScanHeader.d Sat May 17 17:34:28 2008 +0200 @@ -16,7 +16,7 @@ import dwt.internal.image.JPEGVariableSizeSegment; import dwt.internal.image.LEDataInputStream; import dwt.internal.image.JPEGFileFormat; -import dwt.dwthelper.System; +import dwt.dwthelper.utils; final class JPEGScanHeader : JPEGVariableSizeSegment { public int[][] componentParameters; @@ -95,7 +95,7 @@ reference[(2 * getNumberOfImageComponents()) + 5] = cast(byte)anInteger; } -override public int signature() { +public override int signature() { return JPEGFileFormat.SOS; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/JPEGStartOfImage.d --- a/dwt/internal/image/JPEGStartOfImage.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/JPEGStartOfImage.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -30,11 +30,11 @@ super(byteStream); } - override public int signature() { + public override int signature() { return JPEGFileFormat.SOI; } - override public int fixedSize() { + public override int fixedSize() { return 2; } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/LEDataInputStream.d --- a/dwt/internal/image/LEDataInputStream.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/LEDataInputStream.d Sat May 17 17:34:28 2008 +0200 @@ -51,7 +51,7 @@ else throw new IllegalArgumentException("bufferSize must be greater zero" ); } - override public void close() { + public void close() { buf = null; if (host !is null) { host.close(); @@ -69,7 +69,7 @@ /** * Answers how many bytes are available for reading without blocking */ - override public int available() { + public override int available() { if (buf is null) throw new IOException("buf is null"); return (buf.length - pos) + host.available(); } @@ -77,7 +77,7 @@ /** * Answer the next byte of the input stream. */ - override public int read() { + public override int read() { if (buf is null) throw new IOException("buf is null"); if (pos < buf.length) { position++; @@ -92,15 +92,15 @@ * Don't imitate the JDK behaviour of reading a random number * of bytes when you can actually read them all. */ - override public int read(byte b[], int off, int len) { - int read_ = 0, count; - while (read_ !is len && (count = readData(b, off, len - read_)) !is -1) { + public override int read(byte b[], int off, int len) { + int read = 0, count; + while (read !is len && (count = readData(b, off, len - read)) !is -1) { off += count; - read_ += count; + read += count; } - position += read_; - if (read_ is 0 && read_ !is len) return -1; - return read_; + position += read; + if (read is 0 && read !is len) return -1; + return read; } /** @@ -143,6 +143,7 @@ if (cacheCopied is len) return len; int inCopied = host.read( buffer, newOffset, len - cacheCopied ); + if( inCopied is -1 ) inCopied = -1; if (inCopied > 0 ) return inCopied + cacheCopied; if (cacheCopied is 0) return inCopied; return cacheCopied; @@ -155,9 +156,9 @@ public int readInt() { byte[4] buf = void; read(buf); - return ((((((buf[3] & 0xFF) << 24) | - (buf[2] & 0xFF)) << 16) | - (buf[1] & 0xFF)) << 8) | + return ((buf[3] & 0xFF) << 24) | + ((buf[2] & 0xFF) << 16) | + ((buf[1] & 0xFF) << 8) | (buf[0] & 0xFF); } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/LEDataOutputStream.d --- a/dwt/internal/image/LEDataOutputStream.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/LEDataOutputStream.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -16,8 +16,11 @@ import dwt.dwthelper.OutputStream; final class LEDataOutputStream : OutputStream { + alias OutputStream.write write; + OutputStream ostr; + public this(OutputStream output) { this.ostr = output; } @@ -25,13 +28,13 @@ * Write the specified number of bytes of the given byte array, * starting at the specified offset, to the output stream. */ -override public void write(byte b[], int off, int len) { +public override void write(byte b[], int off, int len) { ostr.write(b, off, len); } /** * Write the given byte to the output stream. */ -override public void write(int b) { +public override void write(int b) { ostr.write(b); } /** diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/LZWCodec.d --- a/dwt/internal/image/LZWCodec.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/LZWCodec.d Sat May 17 17:34:28 2008 +0200 @@ -20,9 +20,9 @@ import dwt.graphics.ImageData; import dwt.graphics.ImageLoader; import dwt.graphics.ImageLoaderEvent; +import dwt.dwthelper.utils; import tango.core.Exception; -import dwt.dwthelper.System; final class LZWCodec { int bitsPerPixel, blockSize, blockIndex, currentByte, bitsLeft, diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/OS2BMPFileFormat.d --- a/dwt/internal/image/OS2BMPFileFormat.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/OS2BMPFileFormat.d Sat May 17 17:34:28 2008 +0200 @@ -20,9 +20,9 @@ import dwt.internal.image.LEDataInputStream; import dwt.internal.image.FileFormat; import dwt.dwthelper.ByteArrayOutputStream; +import dwt.dwthelper.utils; import tango.core.Exception; -import dwt.dwthelper.System; final class OS2BMPFileFormat : FileFormat { static final int BMPFileHeaderSize = 14; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PNGFileFormat.d --- a/dwt/internal/image/PNGFileFormat.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PNGFileFormat.d Sat May 17 17:34:28 2008 +0200 @@ -29,9 +29,9 @@ import dwt.internal.image.PngEncoder; import dwt.internal.image.PngInputStream; import dwt.internal.image.PngDecodingDataStream; +import dwt.dwthelper.utils; import dwt.dwthelper.BufferedInputStream; -import dwt.dwthelper.System; import tango.core.Exception; @@ -176,7 +176,7 @@ if ((signature[4] & 0xFF) !is 13) return false; // if ((signature[5] & 0xFF) !is 10) return false; // if ((signature[6] & 0xFF) !is 26) return false; // - if ((signature[7] & 0xFF) !is 10) return false; // + if ((signature[7] & 0xFF) !is 10) return false; // return true; } catch (Exception e) { return false; @@ -314,7 +314,7 @@ bool use3_2 = true;//System.getProperty("dwt.internal.image.PNGFileFormat_3.2") !is null; InputStream inflaterStream = use3_2 ? null : Compatibility.newInflaterInputStream(stream); if (inflaterStream !is null) { - stream = new BufferedInputStream(inflaterStream); + stream = inflaterStream; } else { stream = new PngDecodingDataStream(stream); } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngChunk.d --- a/dwt/internal/image/PngChunk.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngChunk.d Sat May 17 17:34:28 2008 +0200 @@ -21,11 +21,10 @@ import dwt.internal.image.PngIdatChunk; import dwt.internal.image.PngIendChunk; import dwt.internal.image.PngTrnsChunk; +import dwt.dwthelper.utils; import tango.core.Exception; import tango.text.convert.Format; -import dwt.dwthelper.System; -import dwt.dwthelper.utils; class PngChunk { byte[] reference; @@ -53,28 +52,19 @@ static const byte[] TYPE_IEND = cast(byte[])"IEND";//{(byte) 'I', (byte) 'E', (byte) 'N', (byte) 'D'}; static const byte[] TYPE_tRNS = cast(byte[])"tRNS";//{(byte) 't', (byte) 'R', (byte) 'N', (byte) 'S'}; - private static /+const+/ int[] CRC_TABLE; - private static bool static_this_completed = false; - private static void static_this() { - if( static_this_completed ){ - return; - } - synchronized { - if( static_this_completed ){ - return; - } - CRC_TABLE = new int[256]; - for (int i = 0; i < 256; i++) { - CRC_TABLE[i] = i; - for (int j = 0; j < 8; j++) { - if ((CRC_TABLE[i] & 0x1) is 0) { - CRC_TABLE[i] = (CRC_TABLE[i] >> 1) & 0x7FFFFFFF; - } else { - CRC_TABLE[i] = 0xEDB88320 ^ ((CRC_TABLE[i] >> 1) & 0x7FFFFFFF); - } + static const int[] CRC_TABLE; + //public static void static_this() { + static this() { + CRC_TABLE = new int[256]; + for (int i = 0; i < 256; i++) { + CRC_TABLE[i] = i; + for (int j = 0; j < 8; j++) { + if ((CRC_TABLE[i] & 0x1) is 0) { + CRC_TABLE[i] = (CRC_TABLE[i] >> 1) & 0x7FFFFFFF; + } else { + CRC_TABLE[i] = 0xEDB88320 ^ ((CRC_TABLE[i] >> 1) & 0x7FFFFFFF); } } - static_this_completed = true; } } @@ -85,7 +75,6 @@ * given. */ this(byte[] reference) { - static_this(); setReference(reference); if (reference.length < LENGTH_OFFSET + LENGTH_FIELD_LENGTH) DWT.error(DWT.ERROR_INVALID_IMAGE); length = getInt32(LENGTH_OFFSET); @@ -385,7 +374,7 @@ * * @return a string representation of the event */ -override public String toString() { +public override String toString() { String buffer = Format( "{\n\tLength: {}\n\tType: {}{}\n\tCRC: {:X}\n}", getLength(), cast(String) getTypeBytes(), diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngDecodingDataStream.d --- a/dwt/internal/image/PngDecodingDataStream.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngDecodingDataStream.d Sat May 17 17:34:28 2008 +0200 @@ -19,7 +19,9 @@ import dwt.internal.image.PngLzBlockReader; public class PngDecodingDataStream : InputStream { + alias InputStream.read read; + InputStream stream; byte currentByte; int nextBitIndex; @@ -51,7 +53,7 @@ lzBlockReader.assertCompressedDataAtEnd(); } -override public void close() { +public override void close() { assertImageDataAtEnd(); checkAdler(); } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngDeflater.d --- a/dwt/internal/image/PngDeflater.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngDeflater.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -36,7 +36,6 @@ int nextWindow; public this(){ - static_this(); bytes = new ByteArrayOutputStream(1024); } @@ -56,7 +55,7 @@ } -class Match { +static class Match { int length, distance; @@ -121,82 +120,72 @@ } -private static /+const+/ Code lengthCodes[]; -private static /+const+/ Code distanceCodes[]; +static const Code lengthCodes[]; +static const Code distanceCodes[]; -private static bool static_this_completed = false; -private static void static_this() { - if( static_this_completed ){ - return; - } - synchronized { - if( static_this_completed ){ - return; - } - lengthCodes = [ - new Code(257, 0, 3, 3), - new Code(258, 0, 4, 4), - new Code(259, 0, 5, 5), - new Code(260, 0, 6, 6), - new Code(261, 0, 7, 7), - new Code(262, 0, 8, 8), - new Code(263, 0, 9, 9), - new Code(264, 0, 10, 10), - new Code(265, 1, 11, 12), - new Code(266, 1, 13, 14), - new Code(267, 1, 15, 16), - new Code(268, 1, 17, 18), - new Code(269, 2, 19, 22), - new Code(270, 2, 23, 26), - new Code(271, 2, 27, 30), - new Code(272, 2, 31, 34), - new Code(273, 3, 35, 42), - new Code(274, 3, 43, 50), - new Code(275, 3, 51, 58), - new Code(276, 3, 59, 66), - new Code(277, 4, 67, 82), - new Code(278, 4, 83, 98), - new Code(279, 4, 99, 114), - new Code(280, 4, 115, 130), - new Code(281, 5, 131, 162), - new Code(282, 5, 163, 194), - new Code(283, 5, 195, 226), - new Code(284, 5, 227, 257), - new Code(285, 0, 258, 258)]; +static this() { + lengthCodes = [ + new Code(257, 0, 3, 3), + new Code(258, 0, 4, 4), + new Code(259, 0, 5, 5), + new Code(260, 0, 6, 6), + new Code(261, 0, 7, 7), + new Code(262, 0, 8, 8), + new Code(263, 0, 9, 9), + new Code(264, 0, 10, 10), + new Code(265, 1, 11, 12), + new Code(266, 1, 13, 14), + new Code(267, 1, 15, 16), + new Code(268, 1, 17, 18), + new Code(269, 2, 19, 22), + new Code(270, 2, 23, 26), + new Code(271, 2, 27, 30), + new Code(272, 2, 31, 34), + new Code(273, 3, 35, 42), + new Code(274, 3, 43, 50), + new Code(275, 3, 51, 58), + new Code(276, 3, 59, 66), + new Code(277, 4, 67, 82), + new Code(278, 4, 83, 98), + new Code(279, 4, 99, 114), + new Code(280, 4, 115, 130), + new Code(281, 5, 131, 162), + new Code(282, 5, 163, 194), + new Code(283, 5, 195, 226), + new Code(284, 5, 227, 257), + new Code(285, 0, 258, 258)]; - distanceCodes = [ - new Code(0, 0, 1, 1), - new Code(1, 0, 2, 2), - new Code(2, 0, 3, 3), - new Code(3, 0, 4, 4), - new Code(4, 1, 5, 6), - new Code(5, 1, 7, 8), - new Code(6, 2, 9, 12), - new Code(7, 2, 13, 16), - new Code(8, 3, 17, 24), - new Code(9, 3, 25, 32), - new Code(10, 4, 33, 48), - new Code(11, 4, 49, 64), - new Code(12, 5, 65, 96), - new Code(13, 5, 97, 128), - new Code(14, 6, 129, 192), - new Code(15, 6, 193, 256), - new Code(16, 7, 257, 384), - new Code(17, 7, 385, 512), - new Code(18, 8, 513, 768), - new Code(19, 8, 769, 1024), - new Code(20, 9, 1025, 1536), - new Code(21, 9, 1537, 2048), - new Code(22, 10, 2049, 3072), - new Code(23, 10, 3073, 4096), - new Code(24, 11, 4097, 6144), - new Code(25, 11, 6145, 8192), - new Code(26, 12, 8193, 12288), - new Code(27, 12, 12289, 16384), - new Code(28, 13, 16385, 24576), - new Code(29, 13, 24577, 32768)]; - static_this_completed = true; - } + distanceCodes = [ + new Code(0, 0, 1, 1), + new Code(1, 0, 2, 2), + new Code(2, 0, 3, 3), + new Code(3, 0, 4, 4), + new Code(4, 1, 5, 6), + new Code(5, 1, 7, 8), + new Code(6, 2, 9, 12), + new Code(7, 2, 13, 16), + new Code(8, 3, 17, 24), + new Code(9, 3, 25, 32), + new Code(10, 4, 33, 48), + new Code(11, 4, 49, 64), + new Code(12, 5, 65, 96), + new Code(13, 5, 97, 128), + new Code(14, 6, 129, 192), + new Code(15, 6, 193, 256), + new Code(16, 7, 257, 384), + new Code(17, 7, 385, 512), + new Code(18, 8, 513, 768), + new Code(19, 8, 769, 1024), + new Code(20, 9, 1025, 1536), + new Code(21, 9, 1537, 2048), + new Code(22, 10, 2049, 3072), + new Code(23, 10, 3073, 4096), + new Code(24, 11, 4097, 6144), + new Code(25, 11, 6145, 8192), + new Code(26, 12, 8193, 12288), + new Code(27, 12, 12289, 16384), + new Code(28, 13, 16385, 24576), + new Code(29, 13, 24577, 32768)]; } void writeShortLSB(ByteArrayOutputStream baos, int theShort) { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngEncoder.d --- a/dwt/internal/image/PngEncoder.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngEncoder.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -15,10 +15,12 @@ import dwt.internal.image.LEDataOutputStream; import dwt.internal.image.PngDeflater; import dwt.dwthelper.ByteArrayOutputStream; +import dwt.dwthelper.OutputStream; import dwt.DWT; import dwt.graphics.ImageData; import dwt.graphics.ImageLoader; import dwt.graphics.RGB; +import dwt.internal.Compatibility; import dwt.internal.image.PngChunk; import tango.core.Exception; @@ -236,21 +238,23 @@ void writeImageData() { ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + OutputStream os = Compatibility.newDeflaterOutputStream(baos); + if (os is null) os = baos; if (colorType is 3) { - int[] lineData = new int[width]; + byte[] lineData = new byte[width]; for (int y = 0; y < height; y++) { - byte filter[] = [0]; - baos.write(filter, 0, 1); + int filter = 0; + os.write(filter); data.getPixels(0, y, width, lineData, 0); for (int x = 0; x < lineData.length; x++) { - baos.write(cast(byte) lineData[x]); + os.write(lineData[x]); } @@ -261,7 +265,10 @@ else { int[] lineData = new int[width]; - byte[] alphaData = new byte[width]; + byte[] alphaData = null; + if (colorType is 6) { + alphaData = new byte[width]; + } int redMask = data.palette.redMask; int redShift = data.palette.redShift; @@ -272,8 +279,8 @@ for (int y = 0; y < height; y++) { - byte filter[] = [0]; - baos.write(filter, 0, 1); + int filter = 0; + os.write(filter); data.getPixels(0, y, width, lineData, 0); @@ -292,14 +299,12 @@ int b = pixel & blueMask; b = (blueShift < 0) ? b >>> -blueShift : b << blueShift; - byte pixels[] = [cast(byte) r, cast(byte) g, cast(byte) b]; - baos.write(pixels, 0, 3); + os.write(r); + os.write(g); + os.write(b); if (colorType is 6) { - - byte alpha[] = [alphaData[x]]; - baos.write(alpha, 0, 1); - + os.write(alphaData[x]); } } @@ -308,8 +313,14 @@ } - PngDeflater deflater = new PngDeflater(); - byte[] compressed = deflater.deflate(baos.toByteArray()); + os.flush(); + os.close(); + + byte[] compressed = baos.toByteArray(); + if (os is baos) { + PngDeflater deflater = new PngDeflater(); + compressed = deflater.deflate(compressed); + } writeChunk(TAG_IDAT, compressed); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngHuffmanTable.d --- a/dwt/internal/image/PngHuffmanTable.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngHuffmanTable.d Sat May 17 17:34:28 2008 +0200 @@ -116,7 +116,7 @@ return codeValues[index]; } -class CodeLengthInfo { +static class CodeLengthInfo { int length; int max; int min; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngIdatChunk.d --- a/dwt/internal/image/PngIdatChunk.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngIdatChunk.d Sat May 17 17:34:28 2008 +0200 @@ -17,7 +17,7 @@ import dwt.internal.image.PngFileReadState; import dwt.internal.image.PngIhdrChunk; import dwt.internal.image.PngChunk; -import dwt.dwthelper.System; +import dwt.dwthelper.utils; class PngIdatChunk : PngChunk { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngIhdrChunk.d --- a/dwt/internal/image/PngIhdrChunk.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngIhdrChunk.d Sat May 17 17:34:28 2008 +0200 @@ -12,6 +12,8 @@ *******************************************************************************/ module dwt.internal.image.PngIhdrChunk; +import dwt.dwthelper.utils; + import dwt.DWT; import dwt.graphics.PaletteData; @@ -20,7 +22,6 @@ import dwt.internal.image.PngIhdrChunk; import dwt.internal.image.PngChunk; import tango.text.convert.Format; -import dwt.dwthelper.utils; class PngIhdrChunk : PngChunk { static const int IHDR_DATA_LENGTH = 13; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngInputStream.d --- a/dwt/internal/image/PngInputStream.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngInputStream.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -22,6 +22,7 @@ import Math = tango.math.Math; public class PngInputStream : InputStream { + alias InputStream.read read; PngChunkReader reader; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngPlteChunk.d --- a/dwt/internal/image/PngPlteChunk.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngPlteChunk.d Sat May 17 17:34:28 2008 +0200 @@ -12,6 +12,8 @@ *******************************************************************************/ module dwt.internal.image.PngPlteChunk; +import dwt.dwthelper.utils; + import dwt.DWT; import dwt.graphics.PaletteData; @@ -21,7 +23,6 @@ import dwt.internal.image.PngIhdrChunk; import tango.text.convert.Format; -import dwt.dwthelper.utils; class PngPlteChunk : PngChunk { @@ -111,7 +112,7 @@ // Palette chunks' data fields must be event multiples // of 3. Each 3-byte group represents an RGB value. - if (getLength() % 3 !is 0) DWT.error(DWT.ERROR_INVALID_IMAGE); + if (getLength() % 3 !is 0) DWT.error(DWT.ERROR_INVALID_IMAGE); // Palettes cannot have more entries than 2^bitDepth // where bitDepth is the bit depth of the image given diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/PngTrnsChunk.d --- a/dwt/internal/image/PngTrnsChunk.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/PngTrnsChunk.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/TIFFDirectory.d --- a/dwt/internal/image/TIFFDirectory.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/TIFFDirectory.d Sat May 17 17:34:28 2008 +0200 @@ -22,7 +22,6 @@ import dwt.graphics.RGB; import dwt.DWT; import dwt.dwthelper.utils; -import dwt.dwthelper.System; final class TIFFDirectory { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/TIFFFileFormat.d --- a/dwt/internal/image/TIFFFileFormat.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/TIFFFileFormat.d Sat May 17 17:34:28 2008 +0200 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/WinBMPFileFormat.d --- a/dwt/internal/image/WinBMPFileFormat.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/WinBMPFileFormat.d Sat May 17 17:34:28 2008 +0200 @@ -12,15 +12,15 @@ *******************************************************************************/ module dwt.internal.image.WinBMPFileFormat; -public import dwt.internal.image.FileFormat; -public import dwt.graphics.PaletteData; +import dwt.internal.image.FileFormat; +import dwt.graphics.PaletteData; import dwt.graphics.Point; import dwt.graphics.RGB; import dwt.dwthelper.ByteArrayOutputStream; import dwt.DWT; +import dwt.dwthelper.utils; import tango.core.Exception; -import dwt.dwthelper.System; final class WinBMPFileFormat : FileFormat { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/image/WinICOFileFormat.d --- a/dwt/internal/image/WinICOFileFormat.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/image/WinICOFileFormat.d Sat May 17 17:34:28 2008 +0200 @@ -12,15 +12,15 @@ *******************************************************************************/ module dwt.internal.image.WinICOFileFormat; -public import dwt.internal.image.FileFormat; -public import dwt.graphics.PaletteData; +import dwt.internal.image.FileFormat; +import dwt.graphics.PaletteData; import dwt.internal.image.WinBMPFileFormat; import dwt.DWT; +import dwt.dwthelper.utils; import tango.core.Exception; -import dwt.dwthelper.System; -final class WinICOFileFormat : FileFormat { +public final class WinICOFileFormat : FileFormat { byte[] bitInvertData(byte[] data, int startIndex, int endIndex) { // Destructively bit invert data in the given byte array. diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/ole/win32/COM.d --- a/dwt/internal/ole/win32/COM.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/ole/win32/COM.d Sat May 17 17:34:28 2008 +0200 @@ -75,7 +75,7 @@ public static const GUID IIDIAdviseSink = IIDFromStringT!("{0000010F-0000-0000-C000-000000000046}"); //$NON-NLS-1$ //public static const GUID IIDIAdviseSink2 = IIDFromStringT!("{00000125-0000-0000-C000-000000000046}"); //$NON-NLS-1$ //public static const GUID IIDIBindCtx = IIDFromStringT!("{0000000E-0000-0000-C000-000000000046}"); //$NON-NLS-1$ - //public static const GUID IIDIClassFactory = IIDFromStringT!("{00000001-0000-0000-C000-000000000046}"); //$NON-NLS-1$ + public static const GUID IIDIClassFactory = IIDFromStringT!("{00000001-0000-0000-C000-000000000046}"); //$NON-NLS-1$ public static const GUID IIDIClassFactory2 = IIDFromStringT!("{B196B28F-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$ public static const GUID IIDIConnectionPoint = IIDFromStringT!("{B196B286-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$ public static const GUID IIDIConnectionPointContainer = IIDFromStringT!("{B196B284-BAB4-101A-B69C-00AA00341D07}"); //$NON-NLS-1$ @@ -250,13 +250,18 @@ public static const int DISPID_FONT_WEIGHT = 7; public static const int DISPID_FORECOLOR = -513; public static const int DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK = 0xFFFFFDA7; + public static const int DISPID_HTMLDOCUMENTEVENTS_ONDRAGEND = 0x80010015; public static const int DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART = 0x8001000B; + public static const int DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN = 0xFFFFFDA6; + public static const int DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS = 0xFFFFFDA5; + public static const int DISPID_HTMLDOCUMENTEVENTS_ONKEYUP = 0xFFFFFDA4; public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT = 0x80010009; public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER = 0x80010008; public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE = 0xFFFFFDA2; public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN = 0xFFFFFDA3; public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP = 0xFFFFFDA1; public static const int DISPID_HTMLDOCUMENTEVENTS_ONSTOP = 0x00000402; + public static const int DISPID_HTMLDOCUMENTEVENTS_ONMOUSEWHEEL = 1033; //public static const int DISPID_READYSTATE = -525; //public static const int DISPID_READYSTATECHANGE = -609; @@ -268,6 +273,7 @@ public static const int DROPEFFECT_MOVE = 2; public static const int DROPEFFECT_LINK = 4; public static const int DROPEFFECT_SCROLL = 0x80000000; + public static final int DSH_ALLOWDROPDESCRIPTIONTEXT = 0x1; public static const int DV_E_FORMATETC = -2147221404; public static const int DV_E_STGMEDIUM = -2147221402; public static const int DV_E_TYMED = -2147221399; @@ -483,6 +489,7 @@ alias COMAPI.RegisterDragDrop RegisterDragDrop; alias COMAPI.ReleaseStgMedium ReleaseStgMedium; alias COMAPI.RevokeDragDrop RevokeDragDrop; +alias COMAPI.SHDoDragDrop SHDoDragDrop; alias COMAPI.StgCreateDocfile StgCreateDocfile; alias COMAPI.StgIsStorageFile StgIsStorageFile; alias COMAPI.StgOpenStorage StgOpenStorage; @@ -814,7 +821,7 @@ public static const int STATE_SYSTEM_FOCUSED = 0x4; public static const int STATE_SYSTEM_PRESSED = 0x8; public static const int STATE_SYSTEM_CHECKED = 0x10; -//public static const int STATE_SYSTEM_MIXED = 0x20; +public static const int STATE_SYSTEM_MIXED = 0x20; //public static const int STATE_SYSTEM_INDETERMINATE = STATE_SYSTEM_MIXED; public static const int STATE_SYSTEM_READONLY = 0x40; public static const int STATE_SYSTEM_HOTTRACKED = 0x80; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/ole/win32/COMAPI.d --- a/dwt/internal/ole/win32/COMAPI.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/ole/win32/COMAPI.d Sat May 17 17:34:28 2008 +0200 @@ -207,6 +207,13 @@ WINOLEAPI RevokeDragDrop( HWND hwnd //Handle to a window that can accept drops ); +HRESULT SHDoDragDrop( + HWND hwnd, + IDataObject *pdtobj, + IDropSource *pdsrc, + DWORD dwEffect, + DWORD *pdwEffect +); HRESULT StgCreateDocfile( WCHAR* pwcsName, DWORD grfMode, diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/win32/OS.d --- a/dwt/internal/win32/OS.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/win32/OS.d Sat May 17 17:34:28 2008 +0200 @@ -22,7 +22,7 @@ import tango.sys.Common : SysError; static import tango.stdc.stdlib; -import tango.stdc.string : memset; +import tango.stdc.string : memset, strlen; import tango.stdc.stringz : toString16z; import tango.text.convert.Utf : toString16; import tango.io.FilePath; @@ -448,6 +448,7 @@ // public static const int ACTCTX_FLAG_SET_PROCESS_DEFAULT = 0x00000010; public static const int ALTERNATE = 1; public static const int ASSOCF_NOTRUNCATE = 0x00000020; + public static const int ASSOCF_INIT_IGNOREUNKNOWN = 0x400; public static const int ASSOCSTR_COMMAND = 1; public static const int ASSOCSTR_DEFAULTICON = 15; public static const int ASSOCSTR_FRIENDLYAPPNAME = 4; @@ -461,6 +462,12 @@ public static const int AW_HOR_NEGATIVE = 0x00000002; public static const int AW_VER_POSITIVE = 0x00000004; public static const int AW_VER_NEGATIVE = 0x00000008; + public static const int ATTR_INPUT = 0x00; + public static const int ATTR_TARGET_CONVERTED = 0x01; + public static const int ATTR_CONVERTED = 0x02; + public static const int ATTR_TARGET_NOTCONVERTED = 0x03; + public static const int ATTR_INPUT_ERROR = 0x04; + public static const int ATTR_FIXEDCONVERTED = 0x05; public static const int BCM_FIRST = 0x1600; public static const int BCM_GETIDEALSIZE = BCM_FIRST + 0x1; public static const int BCM_GETIMAGELIST = BCM_FIRST + 0x3; @@ -518,7 +525,9 @@ public static const int BP_CHECKBOX = 3; public static const int BP_GROUPBOX = 4; public static const int BST_CHECKED = 0x1; + public static const int BST_INDETERMINATE = 0x2; public static const int BST_UNCHECKED = 0x0; + public static const int BS_3STATE = 0x5; public static const int BS_BITMAP = 0x80; public static const int BS_CENTER = 0x300; public static const int BS_CHECKBOX = 0x2; @@ -594,6 +603,7 @@ public static const int CBXS_HOT = 2; public static const int CBXS_PRESSED = 3; public static const int CBXS_DISABLED = 4; + public static const int CCHILDREN_SCROLLBAR = 5; public static const int CCM_FIRST = 0x2000; public static const int CCM_SETBKCOLOR = 0x2001; public static const int CCM_SETVERSION = 0x2007; @@ -651,6 +661,8 @@ public static const int CFM_WEIGHT = 0x400000; public static const int CFS_POINT = 0x2; public static const int CFS_RECT = 0x1; + public static const int CFS_CANDIDATEPOS = 0x0040; + public static const int CFS_EXCLUDE = 0x0080; public static const int CF_EFFECTS = 0x100; public static const int CF_INITTOLOGFONTSTRUCT = 0x40; public static const int CF_SCREENFONTS = 0x1; @@ -695,6 +707,7 @@ public static const int CP_UTF8 = 65001; public static const int CP_DROPDOWNBUTTON = 1; public static const int CP_INSTALLED = 0x1; + public static const int CPS_COMPLETE = 0x1; public static const int CS_BYTEALIGNWINDOW = 0x2000; public static const int CS_DBLCLKS = 0x8; public static const int CS_DROPSHADOW = 0x20000; @@ -709,6 +722,8 @@ public static const int DCX_CACHE = 0x2; public static const int DCX_CLIPCHILDREN = 0x8; public static const int DCX_CLIPSIBLINGS = 0x10; + public static const int DCX_INTERSECTRGN = 0x80; + public static const int DCX_WINDOW = 0x1; public static const int DEFAULT_CHARSET = 0x1; public static const int DEFAULT_GUI_FONT = 0x11; public static const int DFCS_BUTTONCHECK = 0x0; @@ -759,11 +774,16 @@ public static const int DTM_SETSYSTEMTIME = DTM_FIRST + 2; public static const int DTN_FIRST = 0xFFFFFD08; public static const int DTN_DATETIMECHANGE = DTN_FIRST + 1; + public static const int DTN_CLOSEUP = DTN_FIRST + 7; + public static const int DTN_DROPDOWN = DTN_FIRST + 6; public static const int DTS_LONGDATEFORMAT = 0x0004; public static const int DTS_SHORTDATECENTURYFORMAT = 0x000C; public static const int DTS_SHORTDATEFORMAT = 0x0000; public static const int DTS_TIMEFORMAT = 0x0009; public static const int DTS_UPDOWN = 0x0001; + public static const int DWM_BB_ENABLE = 0x1; + public static const int DWM_BB_BLURREGION = 0x2; + public static const int DWM_BB_TRANSITIONONMAXIMIZED = 0x4; public static const int E_POINTER = 0x80004003; public static const int EBP_NORMALGROUPBACKGROUND = 5; public static const int EBP_NORMALGROUPCOLLAPSE = 6; @@ -856,6 +876,9 @@ public static const int GBS_DISABLED = 2; public static const int GCS_COMPSTR = 0x8; public static const int GCS_RESULTSTR = 0x800; + public static const int GCS_COMPATTR = 0x0010; + public static const int GCS_COMPCLAUSE = 0x0020; + public static const int GCS_CURSORPOS = 0x0080; public static const int GDT_VALID = 0; public static const int GET_FEATURE_FROM_PROCESS = 0x2; public static const int GLPS_CLOSED = 1; @@ -1026,6 +1049,7 @@ public static const int IME_CMODE_KATAKANA = 0x2; public static const int IME_CMODE_NATIVE = 0x1; public static const int IME_CMODE_ROMAN = 0x10; + public static const int IMEMOUSE_LDOWN = 1; public static const int INFINITE = 0xffffffff; public static const int INPUT_KEYBOARD = 1; public static const int INPUT_MOUSE = 0; @@ -1069,6 +1093,7 @@ public static const int LB_RESETCONTENT = 0x184; public static const int LB_SELITEMRANGE = 0x19b; public static const int LB_SELITEMRANGEEX = 0x183; + public static const int LB_SETANCHORINDEX = 0xf19c; public static const int LB_SETCARETINDEX = 0x19e; public static const int LB_SETCURSEL = 0x186; public static const int LB_SETHORIZONTALEXTENT = 0x194; @@ -1201,6 +1226,8 @@ public static const int LVM_SETSELECTEDCOLUMN = LVM_FIRST + 140; public static const int LVM_SETTEXTBKCOLOR = 0x1026; public static const int LVM_SETTEXTCOLOR = 0x1024; + public static const int LVM_SETTOOLTIPS = LVM_FIRST + 74; + public static const int LVM_SUBITEMHITTEST = LVM_FIRST + 57; public static const int LVNI_FOCUSED = 0x1; public static const int LVNI_SELECTED = 0x2; public static const int LVN_BEGINDRAG = 0xffffff93; @@ -1268,6 +1295,7 @@ public static const int MCM_SETCURSEL = MCM_FIRST + 2; public static const int MCN_FIRST = 0xFFFFFD12; public static const int MCN_SELCHANGE = MCN_FIRST + 1; + public static const int MCN_SELECT = MCN_FIRST + 4; public static const int MCM_GETMINREQRECT = MCM_FIRST + 9; public static const int MCS_NOTODAY = 0x0010; public static const int MDIS_ALLCHILDSTYLES = 0x0001; @@ -1294,6 +1322,7 @@ public static const int MIIM_DATA = 0x20; public static const int MIIM_ID = 0x2; public static const int MIIM_STATE = 0x1; + public static const int MIIM_STRING = 0x40; public static const int MIIM_SUBMENU = 0x4; public static const int MIIM_TYPE = 0x10; public static const int MIM_BACKGROUND = 0x2; @@ -1338,6 +1367,7 @@ public static const int MSGF_SIZE = 4; public static const int MSGF_USER = 4096; public static const int MWMO_INPUTAVAILABLE = 0x4; + public static const int NI_COMPOSITIONSTR = 0x15; public static const int NIF_ICON = 0x00000002; public static const int NIF_INFO = 0x00000010; public static const int NIF_MESSAGE = 0x00000001; @@ -1380,6 +1410,8 @@ public static const int OBJ_BITMAP = 0x7; public static const int OBJ_FONT = 0x6; public static const int OBJ_PEN = 0x1; + public static const int OBJID_HSCROLL = 0xFFFFFFFA; + public static const int OBJID_VSCROLL = 0xFFFFFFFB; public static const TCHAR* OBM_CHECKBOXES = cast(TCHAR*)0x7ff7; public static const int ODS_SELECTED = 0x1; public static const int ODT_MENU = 0x1; @@ -1388,6 +1420,7 @@ public static const int OFN_ENABLEHOOK = 0x20; public static const int OFN_HIDEREADONLY = 0x4; public static const int OFN_NOCHANGEDIR = 0x8; + public static const int OFN_OVERWRITEPROMPT = 0x2; public static const int OIC_BANG = 0x7F03; public static const int OIC_HAND = 0x7F01; public static const int OIC_INFORMATION = 0x7F04; @@ -1610,6 +1643,7 @@ public static const int SM_CXDOUBLECLK = 36; public static const int SM_CYDOUBLECLK = 37; public static const int SM_CXEDGE = 0x2d; + public static const int SM_CXFOCUSBORDER = 83; public static const int SM_CXHSCROLL = 0x15; public static const int SM_CXICON = 0x0b; public static const int SM_CYICON = 0x0c; @@ -1623,6 +1657,7 @@ public static const int SM_CXVSCROLL = 0x2; public static const int SM_CYBORDER = 0x6; public static const int SM_CYCURSOR = 0xe; + public static const int SM_CYFOCUSBORDER = 84; public static const int SM_CYHSCROLL = 0x3; public static const int SM_CYMENU = 0xf; public static const int SM_CXMINTRACK = 34; @@ -1635,8 +1670,10 @@ public static const int SPI_GETFONTSMOOTHINGTYPE = 0x200A; public static const int SPI_GETHIGHCONTRAST = 66; public static const int SPI_GETWORKAREA = 0x30; + public static const int SPI_GETMOUSEVANISH = 0x1020; public static const int SPI_GETNONCLIENTMETRICS = 41; public static const int SPI_GETWHEELSCROLLLINES = 104; + public static const int SPI_GETCARETWIDTH = 0x2006; public static const int SPI_SETSIPINFO = 224; public static const int SPI_SETHIGHCONTRAST = 67; public static const int SRCAND = 0x8800c6; @@ -1656,6 +1693,9 @@ public static const int SS_RIGHT = 0x2; public static const int STANDARD_RIGHTS_READ = 0x20000; public static const int STARTF_USESHOWWINDOW = 0x1; + public static const int STATE_SYSTEM_INVISIBLE = 0x00008000; + public static const int STATE_SYSTEM_OFFSCREEN = 0x00010000; + public static const int STATE_SYSTEM_UNAVAILABLE = 0x00000001; public static const int STD_COPY = 0x1; public static const int STD_CUT = 0x0; public static const int STD_FILENEW = 0x6; @@ -1787,6 +1827,7 @@ public static const int TCM_GETITEMCOUNT = 0x1304; public static const int TCM_GETITEMRECT = 0x130a; public static const int TCM_GETTOOLTIPS = 0x132d; + public static const int TCM_HITTEST = 0x130d; public static const int TCM_INSERTITEM = IsUnicode ? 0x133e : 0x1307; public static const int TCM_SETCURSEL = 0x130c; public static const int TCM_SETIMAGELIST = 0x1303; @@ -1799,6 +1840,21 @@ public static const int TCS_TABS = 0x0; public static const int TCS_TOOLTIPS = 0x4000; public static const int TECHNOLOGY = 0x2; + public static const int TF_ATTR_INPUT = 0; + public static const int TF_ATTR_TARGET_CONVERTED = 1; + public static const int TF_ATTR_CONVERTED = 2; + public static const int TF_ATTR_TARGET_NOTCONVERTED = 3; + public static const int TF_ATTR_INPUT_ERROR = 4; + public static const int TF_ATTR_FIXEDCONVERTED = 5; + public static const int TF_ATTR_OTHER = -1; + public alias TF_DA_COLORTYPE.TF_CT_NONE TF_CT_NONE; + public alias TF_DA_COLORTYPE.TF_CT_SYSCOLOR TF_CT_SYSCOLOR; + public alias TF_DA_COLORTYPE.TF_CT_COLORREF TF_CT_COLORREF; + public alias TF_DA_LINESTYLE.TF_LS_NONE TF_LS_NONE; + public alias TF_DA_LINESTYLE.TF_LS_SOLID TF_LS_SOLID; + public alias TF_DA_LINESTYLE.TF_LS_DOT TF_LS_DOT; + public alias TF_DA_LINESTYLE.TF_LS_DASH TF_LS_DASH; + public alias TF_DA_LINESTYLE.TF_LS_SQUIGGLE TF_LS_SQUIGGLE; public static const int TIME_NOSECONDS = 0x2; public static const int TIS_NORMAL = 1; public static const int TIS_HOT = 2; @@ -1864,6 +1920,7 @@ public static const int TTI_ERROR= 3; public static const int TTM_ACTIVATE = 0x400 + 1; public static const int TTM_ADDTOOL = IsUnicode ? 0x432 : 0x404; + public static const int TTM_ADJUSTRECT = 0x400 + 31; public static const int TTM_GETCURRENTTOOLA = 0x400 + 15; public static const int TTM_GETCURRENTTOOLW = 0x400 + 59; public static const int TTM_GETCURRENTTOOL = 0x400 + (IsUnicode ? 59 : 15); @@ -1888,6 +1945,9 @@ public static const int TTN_SHOW = TTN_FIRST - 1; public static const int TTS_ALWAYSTIP = 0x1; public static const int TTS_BALLOON = 0x40; + public static const int TTS_NOANIMATE = 0x10; + public static const int TTS_NOFADE = 0x20; + public static const int TTS_NOPREFIX = 0x02; public static const int TV_FIRST = 0x1100; public static const int TVE_COLLAPSE = 0x1; public static const int TVE_COLLAPSERESET = 0x8000; @@ -1906,6 +1966,8 @@ public static const int TVHT_ONITEM = 0x46; public static const int TVHT_ONITEMBUTTON = 16; public static const int TVHT_ONITEMICON = 0x2; + public static const int TVHT_ONITEMINDENT = 0x8; + public static const int TVHT_ONITEMRIGHT = 0x20; public static const int TVHT_ONITEMLABEL = 0x4; public static const int TVHT_ONITEMSTATEICON = 0x40; public static const int TVIF_HANDLE = 0x10; @@ -1919,10 +1981,10 @@ public static const int TVIS_EXPANDED = 0x20; public static const int TVIS_SELECTED = 0x2; public static const int TVIS_STATEIMAGEMASK = 0xf000; - public static const int TVI_FIRST = 0xffff0001; - public static const int TVI_LAST = 0xffff0002; - public static const int TVI_ROOT = 0xffff0000; - public static const int TVI_SORT = 0xFFFF0003; + public static const int /*long*/ TVI_FIRST = -0x0FFFF; + public static const int /*long*/ TVI_LAST = -0x0FFFE; + public static const int /*long*/ TVI_ROOT = -0x10000; + public static const int /*long*/ TVI_SORT = -0x0FFFD; public static const int TVM_CREATEDRAGIMAGE = TV_FIRST + 18; public static const int TVM_DELETEITEM = 0x1101; public static const int TVM_ENSUREVISIBLE = 0x1114; @@ -1992,6 +2054,7 @@ public static const int TVS_LINESATROOT = 0x4; public static const int TVS_NOHSCROLL = 0x8000; public static const int TVS_NONEVENHEIGHT = 0x4000; + public static const int TVS_NOSCROLL = 0x2000; public static const int TVS_NOTOOLTIPS = 0x80; public static const int TVS_SHOWSELALWAYS = 0x20; public static const int TVS_TRACKSELECT = 0x200; @@ -2008,7 +2071,9 @@ public static const int UDS_ALIGNRIGHT = 0x004; public static const int UDS_AUTOBUDDY = 0x0010; public static const int UDS_WRAP = 0x0001; + public static const int UIS_CLEAR = 2; public static const int UIS_INITIALIZE = 3; + public static const int UIS_SET = 1; public static const int UISF_HIDEACCEL = 0x2; public static const int UISF_HIDEFOCUS = 0x1; public static const TCHAR[] UPDOWN_CLASS = "msctls_updown32"; //$NON-NLS-1$ @@ -2047,7 +2112,6 @@ public static const int VK_MENU = 0x12; public static const int VK_MULTIPLY = 0x6A; public static const int VK_N = 0x4e; - public static const int VK_O = 0x4f; public static const int VK_NEXT = 0x22; public static const int VK_NUMLOCK = 0x90; public static const int VK_NUMPAD0 = 0x60; @@ -2098,6 +2162,7 @@ public static const int WM_ACTIVATE = 0x6; public static const int WM_ACTIVATEAPP = 0x1c; public static const int WM_APP = 0x8000; + public static const int WM_DWMCOLORIZATIONCOLORCHANGED = 0x320; public static const int WM_CANCELMODE = 0x1f; public static const int WM_CAPTURECHANGED = 0x0215; public static const int WM_CHANGEUISTATE = 0x0127; @@ -2132,6 +2197,8 @@ public static const int WM_HSCROLL = 0x114; public static const int WM_IME_CHAR = 0x286; public static const int WM_IME_COMPOSITION = 0x10f; + public static const int WM_IME_COMPOSITION_START = 0x010D; + public static const int WM_IME_ENDCOMPOSITION = 0x010E; public static const int WM_INITDIALOG = 0x110; public static const int WM_INITMENUPOPUP = 0x117; public static const int WM_INPUTLANGCHANGE = 0x51; @@ -2206,8 +2273,10 @@ public static const int WS_CLIPCHILDREN = 0x2000000; public static const int WS_CLIPSIBLINGS = 0x4000000; public static const int WS_DISABLED = 0x4000000; + public static const int WS_EX_APPWINDOW = 0x40000; public static const int WS_EX_CAPTIONOKBTN = 0x80000000; public static const int WS_EX_CLIENTEDGE = 0x200; + public static const int WS_EX_COMPOSITED = 0x2000000; public static const int WS_EX_DLGMODALFRAME = 0x1; public static const int WS_EX_LAYERED = 0x00080000; public static const int WS_EX_LAYOUTRTL = 0x00400000; @@ -2243,7 +2312,7 @@ /++ /** Ansi/Unicode wrappers */ -public static final int /*long*/ AddFontResourceEx (TCHAR lpszFilename, int fl, int /*long*/ pdv) { +public static const int /*long*/ AddFontResourceEx (TCHAR lpszFilename, int fl, int /*long*/ pdv) { if (IsUnicode) { char [] lpszFilename1 = lpszFilename is null ? null : lpszFilename.chars; return AddFontResourceExW (lpszFilename1, fl, pdv); @@ -2252,7 +2321,7 @@ return AddFontResourceExA (lpszFilename1, fl, pdv); } -public static final int /*long*/ AssocQueryString(int flags, int str, TCHAR pszAssoc, TCHAR pszExtra, TCHAR pszOut, int[] pcchOut) { +public static const int /*long*/ AssocQueryString(int flags, int str, TCHAR pszAssoc, TCHAR pszExtra, TCHAR pszOut, int[] pcchOut) { if (IsUnicode) { char [] pszAssoc1 = pszAssoc is null ? null : pszAssoc.chars; char [] pszExtra1 = pszExtra is null ? null : pszExtra.chars; @@ -2265,7 +2334,7 @@ return AssocQueryStringA (flags, str, pszAssoc1, pszExtra1, pszOut1, pcchOut); } -public static final int /*long*/ CallWindowProc (int /*long*/ lpPrevWndFunc, int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) { +public static const int /*long*/ CallWindowProc (int /*long*/ lpPrevWndFunc, int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) { if (IsUnicode) return CallWindowProcW (lpPrevWndFunc, hWnd, Msg, wParam, lParam); return CallWindowProcA (lpPrevWndFunc, hWnd, Msg, wParam, lParam); } @@ -2290,17 +2359,17 @@ return ChooseFontA (chooseFont); } -public static final int /*long*/ CreateActCtx (ACTCTX pActCtx) { +public static const int /*long*/ CreateActCtx (ACTCTX pActCtx) { if (IsUnicode) return CreateActCtxW (pActCtx); return CreateActCtxA (pActCtx); } -public static final int /*long*/ CreateAcceleratorTable (byte [] lpaccl, int cEntries) { +public static const int /*long*/ CreateAcceleratorTable (byte [] lpaccl, int cEntries) { if (IsUnicode) return CreateAcceleratorTableW (lpaccl, cEntries); return CreateAcceleratorTableA (lpaccl, cEntries); } -public static final int /*long*/ CreateDC (TCHAR lpszDriver, TCHAR lpszDevice, int /*long*/ lpszOutput, int /*long*/ lpInitData) { +public static const int /*long*/ CreateDC (TCHAR lpszDriver, TCHAR lpszDevice, int /*long*/ lpszOutput, int /*long*/ lpInitData) { if (IsUnicode) { char [] lpszDriver1 = lpszDriver is null ? null : lpszDriver.chars; char [] lpszDevice1 = lpszDevice is null ? null : lpszDevice.chars; @@ -2311,12 +2380,12 @@ return CreateDCA (lpszDriver1, lpszDevice1, lpszOutput, lpInitData); } -public static final int /*long*/ CreateFontIndirect (int /*long*/ lplf) { +public static const int /*long*/ CreateFontIndirect (int /*long*/ lplf) { if (IsUnicode) return CreateFontIndirectW (lplf); return CreateFontIndirectA (lplf); } -public static final int /*long*/ CreateFontIndirect (LOGFONT lplf) { +public static const int /*long*/ CreateFontIndirect (LOGFONT lplf) { if (IsUnicode) return CreateFontIndirectW ((LOGFONTW)lplf); return CreateFontIndirectA ((LOGFONTA)lplf); } @@ -2326,7 +2395,7 @@ return CreateProcessA (lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); } -public static final int /*long*/ CreateWindowEx (int dwExStyle, TCHAR lpClassName, TCHAR lpWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, int /*long*/ hWndParent, int /*long*/ hMenu, int /*long*/ hInstance, CREATESTRUCT lpParam) { +public static const int /*long*/ CreateWindowEx (int dwExStyle, TCHAR lpClassName, TCHAR lpWindowName, int dwStyle, int X, int Y, int nWidth, int nHeight, int /*long*/ hWndParent, int /*long*/ hMenu, int /*long*/ hInstance, CREATESTRUCT lpParam) { if (IsUnicode) { char [] lpClassName1 = lpClassName is null ? null : lpClassName.chars; char [] lpWindowName1 = lpWindowName is null ? null : lpWindowName.chars; @@ -2337,26 +2406,26 @@ return CreateWindowExA (dwExStyle, lpClassName1, lpWindowName1, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); } -public static final int /*long*/ DefMDIChildProc (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) { +public static const int /*long*/ DefMDIChildProc (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) { if (IsUnicode) return DefMDIChildProcW (hWnd, Msg, wParam, lParam); return DefMDIChildProcA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ DefFrameProc (int /*long*/ hWnd, int /*long*/ hWndMDIClient, int Msg, int /*long*/ wParam, int /*long*/ lParam) { +public static const int /*long*/ DefFrameProc (int /*long*/ hWnd, int /*long*/ hWndMDIClient, int Msg, int /*long*/ wParam, int /*long*/ lParam) { if (IsUnicode) return DefFrameProcW (hWnd, hWndMDIClient, Msg, wParam, lParam); return DefFrameProcA (hWnd, hWndMDIClient, Msg, wParam, lParam); } -public static final int /*long*/ DefWindowProc (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) { +public static const int /*long*/ DefWindowProc (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) { if (IsUnicode) return DefWindowProcW (hWnd, Msg, wParam, lParam); return DefWindowProcA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ DispatchMessage (MSG lpmsg) { +public static const int /*long*/ DispatchMessage (MSG lpmsg) { if (IsUnicode) return DispatchMessageW (lpmsg); return DispatchMessageA (lpmsg); } -public static final int DragQueryFile (int /*long*/ hDrop, int iFile, TCHAR lpszFile, int cch) { +public static const int DragQueryFile (int /*long*/ hDrop, int iFile, TCHAR lpszFile, int cch) { if (IsUnicode) { char [] lpszFile1 = lpszFile is null ? null : lpszFile.chars; return DragQueryFileW (hDrop, iFile, lpszFile1, cch); @@ -2370,7 +2439,7 @@ return DrawStateA (hdc, hbr, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags); } -public static final int DrawText (int /*long*/ hDC, TCHAR lpString, int nCount, RECT lpRect, int uFormat) { +public static const int DrawText (int /*long*/ hDC, TCHAR lpString, int nCount, RECT lpRect, int uFormat) { if (IsUnicode) { char [] lpString1 = lpString is null ? null : lpString.chars; return DrawTextW (hDC, lpString1, nCount, lpRect, uFormat); @@ -2379,7 +2448,7 @@ return DrawTextA (hDC, lpString1, nCount, lpRect, uFormat); } -public static final int EnumFontFamilies (int /*long*/ hdc, TCHAR lpszFamily, int /*long*/ lpEnumFontFamProc, int /*long*/ lParam) { +public static const int EnumFontFamilies (int /*long*/ hdc, TCHAR lpszFamily, int /*long*/ lpEnumFontFamProc, int /*long*/ lParam) { if (IsUnicode) { char [] lpszFamily1 = lpszFamily is null ? null : lpszFamily.chars; return EnumFontFamiliesW (hdc, lpszFamily1, lpEnumFontFamProc, lParam); @@ -2388,7 +2457,7 @@ return EnumFontFamiliesA (hdc, lpszFamily1, lpEnumFontFamProc, lParam); } -public static final int EnumFontFamiliesEx (int /*long*/ hdc, LOGFONT lpLogfont, int /*long*/ lpEnumFontFamExProc, int /*long*/ lParam, int dwFlags) { +public static const int EnumFontFamiliesEx (int /*long*/ hdc, LOGFONT lpLogfont, int /*long*/ lpEnumFontFamExProc, int /*long*/ lParam, int dwFlags) { if (IsUnicode) return EnumFontFamiliesExW (hdc, (LOGFONTW)lpLogfont, lpEnumFontFamExProc, lParam, dwFlags); return EnumFontFamiliesExA (hdc, (LOGFONTA)lpLogfont, lpEnumFontFamExProc, lParam, dwFlags); } @@ -2403,7 +2472,7 @@ return EnumSystemLanguageGroupsA (pLangGroupEnumProc, dwFlags, lParam); } -public static final int ExpandEnvironmentStrings (TCHAR lpSrc, TCHAR lpDst, int nSize) { +public static const int ExpandEnvironmentStrings (TCHAR lpSrc, TCHAR lpDst, int nSize) { if (IsUnicode) { char [] lpSrc1 = lpSrc is null ? null : lpSrc.chars; char [] lpDst1 = lpDst is null ? null : lpDst.chars; @@ -2414,7 +2483,7 @@ return ExpandEnvironmentStringsA (lpSrc1, lpDst1, nSize); } -public static final int ExtractIconEx (TCHAR lpszFile, int nIconIndex, int /*long*/ [] phiconLarge, int /*long*/ [] phiconSmall, int nIcons) { +public static const int ExtractIconEx (TCHAR lpszFile, int nIconIndex, int /*long*/ [] phiconLarge, int /*long*/ [] phiconSmall, int nIcons) { if (IsUnicode) { char [] lpszFile1 = lpszFile is null ? null : lpszFile.chars; return ExtractIconExW (lpszFile1, nIconIndex, phiconLarge, phiconSmall, nIcons); @@ -2432,7 +2501,7 @@ return ExtTextOutA (hdc, X, Y, fuOptions, lprc, lpString1, cbCount, lpDx); } -public static final int /*long*/ FindWindow (TCHAR lpClassName, TCHAR lpWindowName) { +public static const int /*long*/ FindWindow (TCHAR lpClassName, TCHAR lpWindowName) { if (IsUnicode) { char [] lpClassName1 = lpClassName is null ? null : lpClassName.chars; char [] lpWindowName1 = lpWindowName is null ? null : lpWindowName.chars; @@ -2443,7 +2512,7 @@ return FindWindowA (lpClassName1, lpWindowName1); } -public static final int FormatMessage (int dwFlags, int /*long*/ lpSource, int dwMessageId, int dwLanguageId, int[] lpBuffer, int nSize, int /*long*/ Arguments) { +public static const int FormatMessage (int dwFlags, int /*long*/ lpSource, int dwMessageId, int dwLanguageId, int[] lpBuffer, int nSize, int /*long*/ Arguments) { if (IsUnicode) { return FormatMessageW (dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments); } @@ -2455,7 +2524,7 @@ return GetCharABCWidthsA (hdc,iFirstChar, iLastChar, lpabc); } -public static final int GetCharacterPlacement (int /*long*/ hdc, TCHAR lpString, int nCount, int nMaxExtent, GCP_RESULTS lpResults, int dwFlags) { +public static const int GetCharacterPlacement (int /*long*/ hdc, TCHAR lpString, int nCount, int nMaxExtent, GCP_RESULTS lpResults, int dwFlags) { if (IsUnicode) { char [] lpString1 = lpString is null ? null : lpString.chars; return GetCharacterPlacementW (hdc, lpString1, nCount, nMaxExtent, lpResults, dwFlags); @@ -2478,7 +2547,7 @@ return GetClassInfoA (hInstance, lpClassName1, lpWndClass); } -public static final int GetClassName (int /*long*/ hWnd, TCHAR lpClassName, int nMaxCount) { +public static const int GetClassName (int /*long*/ hWnd, TCHAR lpClassName, int nMaxCount) { if (IsUnicode) { char [] lpClassName1 = lpClassName is null ? null : lpClassName.chars; return GetClassNameW (hWnd, lpClassName1, nMaxCount); @@ -2487,7 +2556,7 @@ return GetClassNameA (hWnd, lpClassName1, nMaxCount); } -public static final int GetClipboardFormatName (int format, TCHAR lpszFormatName, int cchMaxCount) { +public static const int GetClipboardFormatName (int format, TCHAR lpszFormatName, int cchMaxCount) { if (IsUnicode) { char [] lpszFormatName1 = lpszFormatName is null ? null : lpszFormatName.chars; return GetClipboardFormatNameW (format, lpszFormatName1, cchMaxCount); @@ -2496,7 +2565,7 @@ return GetClipboardFormatNameA (format, lpszFormatName1, cchMaxCount); } -public static final int GetDateFormat (int Locale, int dwFlags, SYSTEMTIME lpDate, TCHAR lpFormat, TCHAR lpDateStr, int cchDate) { +public static const int GetDateFormat (int Locale, int dwFlags, SYSTEMTIME lpDate, TCHAR lpFormat, TCHAR lpDateStr, int cchDate) { if (IsUnicode) { char [] lpString1 = lpFormat is null ? null : lpFormat.chars; char [] lpString2 = lpDateStr is null ? null : lpDateStr.chars; @@ -2507,7 +2576,7 @@ return GetDateFormatA (Locale, dwFlags, lpDate, lpString1, lpString2, cchDate); } -public static final int GetKeyNameText (int lParam, TCHAR lpString, int nSize) { +public static const int GetKeyNameText (int lParam, TCHAR lpString, int nSize) { if (IsUnicode) { char [] lpString1 = lpString is null ? null : lpString.chars; return GetKeyNameTextW (lParam, lpString1, nSize); @@ -2516,7 +2585,7 @@ return GetKeyNameTextA (lParam, lpString1, nSize); } -public static final int GetLocaleInfo (int Locale, int LCType, TCHAR lpLCData, int cchData) { +public static const int GetLocaleInfo (int Locale, int LCType, TCHAR lpLCData, int cchData) { if (IsUnicode) { char [] lpLCData1 = lpLCData is null ? null : lpLCData.chars; return GetLocaleInfoW (Locale, LCType, lpLCData1, cchData); @@ -2535,7 +2604,7 @@ return GetMessageA (lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); } -public static final int GetModuleFileName (int /*long*/ hModule, TCHAR lpFilename, int inSize) { +public static const int GetModuleFileName (int /*long*/ hModule, TCHAR lpFilename, int inSize) { if (IsUnicode) { char [] lpFilename1 = lpFilename is null ? null : lpFilename.chars; return GetModuleFileNameW (hModule, lpFilename1, inSize); @@ -2544,7 +2613,7 @@ return GetModuleFileNameA (hModule, lpFilename1, inSize); } -public static final int /*long*/ GetModuleHandle (TCHAR lpModuleName) { +public static const int /*long*/ GetModuleHandle (TCHAR lpModuleName) { if (IsUnicode) { char [] lpModuleName1 = lpModuleName is null ? null : lpModuleName.chars; return GetModuleHandleW (lpModuleName1); @@ -2558,37 +2627,37 @@ return GetMonitorInfoA (hmonitor, lpmi); } -public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, BITMAP lpvObject) { +public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, BITMAP lpvObject) { if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject); return GetObjectA (hgdiobj, cbBuffer, lpvObject); } -public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, DIBSECTION lpvObject) { +public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, DIBSECTION lpvObject) { if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject); return GetObjectA (hgdiobj, cbBuffer, lpvObject); } -public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, EXTLOGPEN lpvObject) { +public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, EXTLOGPEN lpvObject) { if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject); return GetObjectA (hgdiobj, cbBuffer, lpvObject); } -public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGBRUSH lpvObject) { +public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGBRUSH lpvObject) { if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject); return GetObjectA (hgdiobj, cbBuffer, lpvObject); } -public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGFONT lpvObject) { +public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGFONT lpvObject) { if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, (LOGFONTW)lpvObject); return GetObjectA (hgdiobj, cbBuffer, (LOGFONTA)lpvObject); } -public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGPEN lpvObject) { +public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, LOGPEN lpvObject) { if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject); return GetObjectA (hgdiobj, cbBuffer, lpvObject); } -public static final int GetObject (int /*long*/ hgdiobj, int cbBuffer, int /*long*/ lpvObject) { +public static const int GetObject (int /*long*/ hgdiobj, int cbBuffer, int /*long*/ lpvObject) { if (IsUnicode) return GetObjectW (hgdiobj, cbBuffer, lpvObject); return GetObjectA (hgdiobj, cbBuffer, lpvObject); } @@ -2598,7 +2667,7 @@ return GetOpenFileNameA (lpofn); } -public static final int GetProfileString (TCHAR lpAppName, TCHAR lpKeyName, TCHAR lpDefault, TCHAR lpReturnedString, int nSize) { +public static const int GetProfileString (TCHAR lpAppName, TCHAR lpKeyName, TCHAR lpDefault, TCHAR lpReturnedString, int nSize) { if (IsUnicode) { char [] lpAppName1 = lpAppName is null ? null : lpAppName.chars; char [] lpKeyName1 = lpKeyName is null ? null : lpKeyName.chars; @@ -2645,7 +2714,7 @@ return GetTextMetricsA (hdc, (TEXTMETRICA)lptm); } -public static final int GetTimeFormat (int Locale, int dwFlags, SYSTEMTIME lpTime, TCHAR lpFormat, TCHAR lpTimeStr, int cchTime) { +public static const int GetTimeFormat (int Locale, int dwFlags, SYSTEMTIME lpTime, TCHAR lpFormat, TCHAR lpTimeStr, int cchTime) { if (IsUnicode) { char [] lpString1 = lpFormat is null ? null : lpFormat.chars; char [] lpString2 = lpTimeStr is null ? null : lpTimeStr.chars; @@ -2666,17 +2735,17 @@ return GetVersionExA ((OSVERSIONINFOEXA)lpVersionInfo); } -public static final int GetWindowLong (int /*long*/ hWnd, int nIndex) { +public static const int GetWindowLong (int /*long*/ hWnd, int nIndex) { if (IsUnicode) return GetWindowLongW (hWnd, nIndex); return GetWindowLongA (hWnd, nIndex); } -public static final int /*long*/ GetWindowLongPtr (int /*long*/ hWnd, int nIndex) { +public static const int /*long*/ GetWindowLongPtr (int /*long*/ hWnd, int nIndex) { if (IsUnicode) return GetWindowLongPtrW (hWnd, nIndex); return GetWindowLongPtrA (hWnd, nIndex); } -public static final int GetWindowText (int /*long*/ hWnd, TCHAR lpString, int nMaxCount) { +public static const int GetWindowText (int /*long*/ hWnd, TCHAR lpString, int nMaxCount) { if (IsUnicode) { char [] lpString1 = lpString is null ? null : lpString.chars; return GetWindowTextW (hWnd, lpString1, nMaxCount); @@ -2685,12 +2754,12 @@ return GetWindowTextA (hWnd, lpString1, nMaxCount); } -public static final int GetWindowTextLength (int /*long*/ hWnd) { +public static const int GetWindowTextLength (int /*long*/ hWnd) { if (IsUnicode) return GetWindowTextLengthW (hWnd); return GetWindowTextLengthA (hWnd); } -public static final int GlobalAddAtom (TCHAR lpString) { +public static const int GlobalAddAtom (TCHAR lpString) { if (IsUnicode) { char [] lpString1 = lpString is null ? null : lpString.chars; return GlobalAddAtomW (lpString1); @@ -2709,7 +2778,7 @@ return ImmSetCompositionFontA (hIMC, (LOGFONTA)lplf); } -public static final int ImmGetCompositionString (int /*long*/ hIMC, int dwIndex, TCHAR lpBuf, int dwBufLen) { +public static const int ImmGetCompositionString (int /*long*/ hIMC, int dwIndex, TCHAR lpBuf, int dwBufLen) { if (IsUnicode) { char [] lpBuf1 = lpBuf is null ? null : lpBuf.chars; return ImmGetCompositionStringW (hIMC, dwIndex, lpBuf1, dwBufLen); @@ -2732,22 +2801,22 @@ return InsertMenuItemA (hMenu, uItem, fByPosition, lpmii); } -public static final int /*long*/ LoadBitmap (int /*long*/ hInstance, int /*long*/ lpBitmapName) { +public static const int /*long*/ LoadBitmap (int /*long*/ hInstance, int /*long*/ lpBitmapName) { if (IsUnicode) return LoadBitmapW (hInstance, lpBitmapName); return LoadBitmapA (hInstance, lpBitmapName); } -public static final int /*long*/ LoadCursor (int /*long*/ hInstance, int /*long*/ lpCursorName) { +public static const int /*long*/ LoadCursor (int /*long*/ hInstance, int /*long*/ lpCursorName) { if (IsUnicode) return LoadCursorW (hInstance, lpCursorName); return LoadCursorA (hInstance, lpCursorName); } -public static final int /*long*/ LoadIcon (int /*long*/ hInstance, int /*long*/ lpIconName) { +public static const int /*long*/ LoadIcon (int /*long*/ hInstance, int /*long*/ lpIconName) { if (IsUnicode) return LoadIconW (hInstance, lpIconName); return LoadIconA (hInstance, lpIconName); } -public static final int /*long*/ LoadImage (int /*long*/ hinst, TCHAR lpszName, int uType, int cxDesired, int cyDesired, int fuLoad) { +public static const int /*long*/ LoadImage (int /*long*/ hinst, TCHAR lpszName, int uType, int cxDesired, int cyDesired, int fuLoad) { if (IsUnicode) { char [] lpszName1 = lpszName is null ? null : lpszName.chars; return LoadImageW (hinst, lpszName1, uType, cxDesired, cyDesired, fuLoad); @@ -2756,12 +2825,12 @@ return LoadImageA (hinst, lpszName1, uType, cxDesired, cyDesired, fuLoad); } -public static final int /*long*/ LoadImage (int /*long*/ hinst, int /*long*/ lpszName, int uType, int cxDesired, int cyDesired, int fuLoad) { +public static const int /*long*/ LoadImage (int /*long*/ hinst, int /*long*/ lpszName, int uType, int cxDesired, int cyDesired, int fuLoad) { if (IsUnicode) return LoadImageW (hinst, lpszName, uType, cxDesired, cyDesired, fuLoad); return LoadImageA (hinst, lpszName, uType, cxDesired, cyDesired, fuLoad); } -public static final int /*long*/ LoadLibrary (TCHAR lpLibFileName) { +public static const int /*long*/ LoadLibrary (TCHAR lpLibFileName) { if (IsUnicode) { char [] lpLibFileName1 = lpLibFileName is null ? null : lpLibFileName.chars; return LoadLibraryW (lpLibFileName1); @@ -2770,7 +2839,7 @@ return LoadLibraryA (lpLibFileName1); } -public static final int LoadString (int /*long*/ hinst, int uID, TCHAR lpBuffer, int nBufferMax) { +public static const int LoadString (int /*long*/ hinst, int uID, TCHAR lpBuffer, int nBufferMax) { if (IsUnicode) { char [] lpBuffer1 = lpBuffer is null ? null : lpBuffer.chars; return LoadStringW (hinst, uID, lpBuffer1, nBufferMax); @@ -2779,12 +2848,12 @@ return LoadStringA (hinst, uID, lpBuffer1, nBufferMax); } -public static final int MapVirtualKey (int uCode, int uMapType) { +public static const int MapVirtualKey (int uCode, int uMapType) { if (IsUnicode) return MapVirtualKeyW (uCode, uMapType); return MapVirtualKeyA (uCode, uMapType); } -public static final int MessageBox (int /*long*/ hWnd, TCHAR lpText, TCHAR lpCaption, int uType) { +public static const int MessageBox (int /*long*/ hWnd, TCHAR lpText, TCHAR lpCaption, int uType) { if (IsUnicode) { char [] lpText1 = lpText is null ? null : lpText.chars; char [] lpCaption1 = lpCaption is null ? null : lpCaption.chars; @@ -2875,7 +2944,7 @@ return PrintDlgA (lppd); } -public static final int RegEnumKeyEx (int /*long*/ hKey, int dwIndex, TCHAR lpName, int [] lpcName, int [] lpReserved, TCHAR lpClass, int [] lpcClass, FILETIME lpftLastWriteTime) { +public static const int RegEnumKeyEx (int /*long*/ hKey, int dwIndex, TCHAR lpName, int [] lpcName, int [] lpReserved, TCHAR lpClass, int [] lpcClass, FILETIME lpftLastWriteTime) { if (IsUnicode) { char [] lpName1 = lpName is null ? null : lpName.chars; char [] lpClass1 = lpClass is null ? null : lpClass.chars; @@ -2886,12 +2955,12 @@ return RegEnumKeyExA (hKey, dwIndex, lpName1, lpcName, lpReserved, lpClass1, lpcClass, lpftLastWriteTime); } -public static final int RegisterClass (WNDCLASS lpWndClass) { +public static const int RegisterClass (WNDCLASS lpWndClass) { if (IsUnicode) return RegisterClassW (lpWndClass); return RegisterClassA (lpWndClass); } -public static final int RegisterClipboardFormat (TCHAR lpszFormat) { +public static const int RegisterClipboardFormat (TCHAR lpszFormat) { if (IsUnicode) { char [] lpszFormat1 = lpszFormat is null ? null : lpszFormat.chars; return RegisterClipboardFormatW (lpszFormat1); @@ -2900,7 +2969,7 @@ return RegisterClipboardFormatA (lpszFormat1); } -public static final int RegisterWindowMessage (TCHAR lpString) { +public static const int RegisterWindowMessage (TCHAR lpString) { if (IsUnicode) { char [] lpString1 = lpString is null ? null : lpString.chars; return RegisterWindowMessageW (lpString1); @@ -2909,7 +2978,7 @@ return RegisterWindowMessageA (lpString1); } -public static final int RegOpenKeyEx (int /*long*/ hKey, TCHAR lpSubKey, int ulOptions, int samDesired, int /*long*/[] phkResult) { +public static const int RegOpenKeyEx (int /*long*/ hKey, TCHAR lpSubKey, int ulOptions, int samDesired, int /*long*/[] phkResult) { if (IsUnicode) { char [] lpSubKey1 = lpSubKey is null ? null : lpSubKey.chars; return RegOpenKeyExW (hKey, lpSubKey1, ulOptions, samDesired, phkResult); @@ -2918,12 +2987,12 @@ return RegOpenKeyExA (hKey, lpSubKey1, ulOptions, samDesired, phkResult); } -public static final int RegQueryInfoKey (int /*long*/ hKey, int /*long*/ lpClass, int[] lpcbClass, int /*long*/ lpReserved, int[] lpSubKeys, int[] lpcbMaxSubKeyLen, int[] lpcbMaxClassLen, int[] lpcValues, int[] lpcbMaxValueNameLen, int[] lpcbMaxValueLen, int[] lpcbSecurityDescriptor, int /*long*/ lpftLastWriteTime){ +public static const int RegQueryInfoKey (int /*long*/ hKey, int /*long*/ lpClass, int[] lpcbClass, int /*long*/ lpReserved, int[] lpSubKeys, int[] lpcbMaxSubKeyLen, int[] lpcbMaxClassLen, int[] lpcValues, int[] lpcbMaxValueNameLen, int[] lpcbMaxValueLen, int[] lpcbSecurityDescriptor, int /*long*/ lpftLastWriteTime){ if (IsUnicode) return RegQueryInfoKeyW (hKey, lpClass, lpcbClass, lpReserved, lpSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime); return RegQueryInfoKeyA (hKey, lpClass, lpcbClass, lpReserved, lpSubKeys, lpcbMaxSubKeyLen, lpcbMaxClassLen, lpcValues, lpcbMaxValueNameLen, lpcbMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime); } -public static final int RegQueryValueEx (int /*long*/ hKey, TCHAR lpValueName, int /*long*/ lpReserved, int[] lpType, TCHAR lpData, int[] lpcbData) { +public static const int RegQueryValueEx (int /*long*/ hKey, TCHAR lpValueName, int /*long*/ lpReserved, int[] lpType, TCHAR lpData, int[] lpcbData) { if (IsUnicode) { char [] lpValueName1 = lpValueName is null ? null : lpValueName.chars; char [] lpData1 = lpData is null ? null : lpData.chars; @@ -2934,7 +3003,7 @@ return RegQueryValueExA (hKey, lpValueName1, lpReserved, lpType, lpData1, lpcbData); } -public static final int RegQueryValueEx (int /*long*/ hKey, TCHAR lpValueName, int /*long*/ lpReserved, int[] lpType, int [] lpData, int[] lpcbData) { +public static const int RegQueryValueEx (int /*long*/ hKey, TCHAR lpValueName, int /*long*/ lpReserved, int[] lpType, int [] lpData, int[] lpcbData) { if (IsUnicode) { char [] lpValueName1 = lpValueName is null ? null : lpValueName.chars; return RegQueryValueExW (hKey, lpValueName1, lpReserved, lpType, lpData, lpcbData); @@ -2943,12 +3012,12 @@ return RegQueryValueExA (hKey, lpValueName1, lpReserved, lpType, lpData, lpcbData); } -public static final int /*long*/ RemoveProp (int /*long*/ hWnd, int /*long*/ lpString){ +public static const int /*long*/ RemoveProp (int /*long*/ hWnd, int /*long*/ lpString){ if (IsUnicode) return RemovePropW (hWnd, lpString); return RemovePropA (hWnd, lpString); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TCHAR lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TCHAR lParam) { if (IsUnicode) { char [] lParam1 = lParam is null ? null : lParam.chars; return SendMessageW (hWnd, Msg, wParam, lParam1); @@ -2957,147 +3026,147 @@ return SendMessageA (hWnd, Msg, wParam, lParam1); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int [] wParam, int [] lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int [] wParam, int [] lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, SIZE lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, SIZE lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ [] wParam, int /*long*/ lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ [] wParam, int /*long*/ lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int [] lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int [] lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, char [] lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, char [] lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, short [] lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, short [] lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, int /*long*/ lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LITEM lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LITEM lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVCOLUMN lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVCOLUMN lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVHITTESTINFO lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVHITTESTINFO lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVITEM lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, LVITEM lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, MARGINS lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, MARGINS lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, POINT lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, POINT lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, REBARBANDINFO lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, REBARBANDINFO lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, RECT lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, RECT lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, SYSTEMTIME lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, SYSTEMTIME lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TBBUTTON lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TBBUTTON lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TBBUTTONINFO lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TBBUTTONINFO lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TCITEM lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TCITEM lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TOOLINFO lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TOOLINFO lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVHITTESTINFO lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVHITTESTINFO lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVINSERTSTRUCT lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVINSERTSTRUCT lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVITEM lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVITEM lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVSORTCB lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, TVSORTCB lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, UDACCEL lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, UDACCEL lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDHITTESTINFO lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDHITTESTINFO lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDITEM lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDITEM lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDLAYOUT lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, HDLAYOUT lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } -public static final int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, BUTTON_IMAGELIST lParam) { +public static const int /*long*/ SendMessage (int /*long*/ hWnd, int Msg, int /*long*/ wParam, BUTTON_IMAGELIST lParam) { if (IsUnicode) return SendMessageW (hWnd, Msg, wParam, lParam); return SendMessageA (hWnd, Msg, wParam, lParam); } @@ -3112,17 +3181,17 @@ return SetPropA (hWnd, lpString, hData); } -public static final int SetWindowLong (int /*long*/ hWnd, int nIndex, int dwNewLong) { +public static const int SetWindowLong (int /*long*/ hWnd, int nIndex, int dwNewLong) { if (IsUnicode) return SetWindowLongW (hWnd, nIndex, dwNewLong); return SetWindowLongA (hWnd, nIndex, dwNewLong); } -public static final int /*long*/ SetWindowLongPtr (int /*long*/ hWnd, int nIndex, int /*long*/ dwNewLong) { +public static const int /*long*/ SetWindowLongPtr (int /*long*/ hWnd, int nIndex, int /*long*/ dwNewLong) { if (IsUnicode) return SetWindowLongPtrW (hWnd, nIndex, dwNewLong); return SetWindowLongPtrA (hWnd, nIndex, dwNewLong); } -public static final int /*long*/ SetWindowsHookEx (int idHook, int /*long*/ lpfn, int /*long*/ hMod, int dwThreadId) { +public static const int /*long*/ SetWindowsHookEx (int idHook, int /*long*/ lpfn, int /*long*/ hMod, int dwThreadId) { if (IsUnicode) return SetWindowsHookExW (idHook, lpfn, hMod, dwThreadId); return SetWindowsHookExA (idHook, lpfn, hMod, dwThreadId); } @@ -3136,7 +3205,7 @@ return SetWindowTextA (hWnd, lpString1); } -public static final int /*long*/ SHBrowseForFolder (BROWSEINFO lpbi) { +public static const int /*long*/ SHBrowseForFolder (BROWSEINFO lpbi) { if (IsUnicode) return SHBrowseForFolderW (lpbi); return SHBrowseForFolderA (lpbi); } @@ -3169,7 +3238,7 @@ return SHGetPathFromIDListA (pidl, pszPath1); } -public static final int StartDoc (int /*long*/ hdc, DOCINFO lpdi) { +public static const int StartDoc (int /*long*/ hdc, DOCINFO lpdi) { if (IsUnicode) return StartDocW (hdc, lpdi); return StartDocA (hdc, lpdi); } @@ -3194,7 +3263,7 @@ return SystemParametersInfoA (uiAction, uiParam, pvParam, fWinIni); } -public static final int TranslateAccelerator (int /*long*/ hWnd, int /*long*/ hAccTable, MSG lpMsg) { +public static const int TranslateAccelerator (int /*long*/ hWnd, int /*long*/ hAccTable, MSG lpMsg) { if (IsUnicode) return TranslateAcceleratorW (hWnd, hAccTable, lpMsg); return TranslateAcceleratorA (hWnd, hAccTable, lpMsg); } @@ -4026,6 +4095,7 @@ alias WINAPI.GetTextMetricsA GetTextMetrics; alias WINAPI.GetVersionExA GetVersionEx; alias WINAPI.GetWindowLongA GetWindowLong; + alias WINAPI.GetWindowLongPtrA GetWindowLongPtr; alias WINAPI.GetWindowTextA _GetWindowText; alias WINAPI.GetWindowTextLengthA GetWindowTextLength; alias WINAPI.GlobalAddAtomA GlobalAddAtom; @@ -4062,6 +4132,7 @@ alias WINAPI.SetMenuItemInfoA SetMenuItemInfo; alias WINAPI.SetPropA SetProp; alias WINAPI.SetWindowLongA SetWindowLong; + alias WINAPI.SetWindowLongPtrA SetWindowLongPtr; alias WINAPI.SetWindowTextA SetWindowText; alias WINAPI.SetWindowsHookExA SetWindowsHookEx; alias WINAPI.ShellExecuteExA ShellExecuteEx; @@ -4129,6 +4200,7 @@ alias WINAPI.GetTextMetricsW GetTextMetrics; alias WINAPI.GetVersionExW GetVersionEx; alias WINAPI.GetWindowLongW GetWindowLong; + alias WINAPI.GetWindowLongPtrW GetWindowLongPtr; alias WINAPI.GetWindowTextW _GetWindowText; alias WINAPI.GetWindowTextLengthW GetWindowTextLength; alias WINAPI.GlobalAddAtomW GlobalAddAtom; @@ -4164,6 +4236,7 @@ alias WINAPI.SendMessageW SendMessage; alias WINAPI.SetMenuItemInfoW SetMenuItemInfo; alias WINAPI.SetWindowLongW SetWindowLong; + alias WINAPI.SetWindowLongPtrW SetWindowLongPtr; alias WINAPI.SetWindowTextW SetWindowText; alias WINAPI.SetWindowsHookExW SetWindowsHookEx; alias WINAPI.SetPropW SetProp; @@ -4318,8 +4391,15 @@ // this function vars exist primarily for link error elimination //---------------------------------------------------------------------- public static extern(Windows) { + + BOOL function( + HIMC hIMC, + LPCANDIDATEFORM lpCandidate + ) ImmSetCandidateWindow; + } // public static extern(Windows) + static Symbol[] Symbols_CoreImm = [ ]; @@ -4327,6 +4407,7 @@ public static extern(Windows) BOOL function() SetProcessDPIAware; static Symbol[] Symbols_User32 = [ { "SetProcessDPIAware", cast(void**)& SetProcessDPIAware, 6, 0 }, + { "ImmSetCandidateWindow", cast(void**)& ImmSetCandidateWindow, 6, 0 }, ]; // Imm32.lib @@ -4354,7 +4435,26 @@ BOOL function( HIMC hIMC, LPCOMPOSITIONFORM lpCompForm ) ImmSetCompositionWindow; BOOL function( HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence ) ImmSetConversionStatus; BOOL function( HIMC hIMC, BOOL fOpen ) ImmSetOpenStatus; - +BOOL function( + HIMC hIMC, + DWORD dwAction, + DWORD dwIndex, + DWORD dwValue +)ImmNotifyIME; + +LONG function( + HIMC hIMC, + DWORD dwIndex, + LPVOID lpBuf, + DWORD dwBufLen +) ImmGetCompositionStringA; + +LONG function( + HIMC hIMC, + DWORD dwIndex, + LPVOID lpBuf, + DWORD dwBufLen +) ImmGetCompositionStringW; } static Symbol[] Symbols_Imm32 = [ @@ -4373,6 +4473,9 @@ { "ImmSetConversionStatus", cast(void**)& ImmSetConversionStatus, 5, 1 }, { "ImmSetOpenStatus", cast(void**)& ImmSetOpenStatus, 5, 1 }, { "ImmDisableTextFrameService", cast(void**)& ImmDisableTextFrameService, 5, 1 }, + { "ImmNotifyIME", cast(void**)& ImmNotifyIME, 5, 1 }, + { "ImmGetCompositionStringW", cast(void**)& ImmGetCompositionStringW, 5, 1 }, + { "ImmGetCompositionStringA", cast(void**)& ImmGetCompositionStringA, 5, 1 }, ]; // kernel32 winxp/vista @@ -5083,9 +5186,50 @@ return fn(ppVtbl, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); } - +public static int LOWORD (int /*long*/ l){ + return l & 0xFFFF; +} +public static int HIWORD (int /*long*/ h){ + return h >> 16; +} +//public static bool LPtoDP (int /*long*/ hdc, POINT lpPoints, int nCount); +public static int MAKEWORD(int l, int h){ + return ( h << 16 )|( l &0xFFFF ); +} +public static int /*long*/ MAKEWPARAM(int l, int h); +public static int /*long*/ MAKELPARAM(int l, int h); +public static int /*long*/ MAKELRESULT(int l, int h); +public static int GET_WHEEL_DELTA_WPARAM(int /*long*/ wParam); + +public static int GET_X_LPARAM(int /*long*/ lp){ + return cast(short) (lp & 0xFFFF); +} + +public static int GET_Y_LPARAM(int /*long*/ lp){ + return cast(short) (lp >> 16); +} + +alias WINAPI.GetOutlineTextMetrics GetOutlineTextMetrics; + +static bool TreeView_GetItemRect( HWND hwnd, HTREEITEM hitem, RECT* prc, bool code) { + *cast(HTREEITEM *)prc = hitem; + return cast(bool) SendMessage( hwnd, TVM_GETITEMRECT, code, cast(int)prc ); +} +static int strlen( char* ptr ){ + return tango.stdc.string.strlen( ptr ); +} +alias WINAPI.GetLayeredWindowAttributes GetLayeredWindowAttributes; +alias WINAPI.SetLayeredWindowAttributes SetLayeredWindowAttributes; + +static void POINTSTOPOINT( inout POINT pt, int pts) { + pt.x = cast(SHORT) LOWORD(pts); + pt.y = cast(SHORT) HIWORD(pts); +} + +alias WINAPI.GetScrollBarInfo GetScrollBarInfo; +alias WINAPI.PrintWindow PrintWindow; } // END of OS - +//----------------------------------------------------------------------------- import tango.sys.win32.CodePage : CodePage; private import tango.text.convert.Utf; private import tango.stdc.stringz; @@ -5293,8 +5437,11 @@ TCHAR[] NewTCHARs( uint codepage, uint len ){ - return new TCHAR[ len ]; -} - - - + auto res = new TCHAR[ len ]; + res[] = '\0'; + return res; +} + + + + diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/win32/WINAPI.d --- a/dwt/internal/win32/WINAPI.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/win32/WINAPI.d Sat May 17 17:34:28 2008 +0200 @@ -2099,18 +2099,17 @@ DEVMODE *lpInitData // pointer to optional printer data ); - HBITMAP CreateDIBSection( - HDC hdc, // handle to device context - BITMAPINFO *pbmi, - // pointer to structure containing bitmap size, - // format, and color data - UINT iUsage, // color data type indicator: RGB values or - // palette indexes - VOID *ppvBits, // pointer to variable to receive a pointer to - // the bitmap's bit values - HANDLE hSection, // optional handle to a file mapping object - DWORD dwOffset // offset to the bitmap bit values within the - // file mapping object +HBITMAP CreateDIBSection( + HDC hdc, // handle to device context + BITMAPINFO *pbmi, // pointer to structure containing bitmap size, + // format, and color data + UINT iUsage, // color data type indicator: RGB values or + // palette indexes + VOID **ppvBits, // pointer to variable to receive a pointer to + // the bitmap's bit values + HANDLE hSection, // optional handle to a file mapping object + DWORD dwOffset // offset to the bitmap bit values within the + // file mapping object ); HANDLE CreateEventA( LPSECURITY_ATTRIBUTES lpEventAttributes, @@ -2858,6 +2857,16 @@ ); LONG GetWindowLongA(HWND hWnd, int nIndex); LONG GetWindowLongW(HWND hWnd, int nIndex); + +LONG_PTR GetWindowLongPtrA( + HWND hWnd, + int nIndex +); +LONG_PTR GetWindowLongPtrW( + HWND hWnd, + int nIndex +); + BOOL GetWindowPlacement( HWND hWnd, WINDOWPLACEMENT *lpwndpl @@ -3641,6 +3650,19 @@ int nIndex, LONG dwNewLong ); + +LONG_PTR SetWindowLongPtrA( + HWND hWnd, + int nIndex, + LONG_PTR dwNewLong +); + +LONG_PTR SetWindowLongPtrW( + HWND hWnd, + int nIndex, + LONG_PTR dwNewLong +); + BOOL SetWindowPlacement( HWND hWnd, WINDOWPLACEMENT *lpwndpl @@ -3799,6 +3821,36 @@ SHORT VkKeyScanA(char ch); SHORT VkKeyScanW(wchar ch); BOOL WaitMessage(); + +UINT GetOutlineTextMetrics( + HDC hdc, + UINT cbData, + LPOUTLINETEXTMETRICW lpOTM +); + +BOOL GetLayeredWindowAttributes( + HWND hwnd, + COLORREF *pcrKey, + BYTE *pbAlpha, + DWORD *pdwFlags +); +BOOL SetLayeredWindowAttributes( + HWND hwnd, + COLORREF crKey, + BYTE bAlpha, + DWORD dwFlags +); +BOOL GetScrollBarInfo( + HWND hwnd, + LONG idObject, + PSCROLLBARINFO psbi +); +BOOL PrintWindow( + HWND hwnd, // Window to copy + HDC hdcBlt, // HDC to print into + UINT nFlags // Optional flags +); + } extern (C) diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/internal/win32/WINTYPES.d --- a/dwt/internal/win32/WINTYPES.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/internal/win32/WINTYPES.d Sat May 17 17:34:28 2008 +0200 @@ -11192,46 +11192,52 @@ // alias TEXTMETRIC TTEXTMETRIC; // alias TEXTMETRIC* PTEXTMETRIC; -struct OUTLINETEXTMETRIC -{ - UINT otmSize; - TEXTMETRIC otmTextMetrics; - ubyte otmFiller; - PANOSE otmPanoseNumber; - UINT otmfsSelection; - UINT otmfsType; - int otmsCharSlopeRise; - int otmsCharSlopeRun; - int otmItalicAngle; - UINT otmEMSquare; - int otmAscent; - int otmDescent; - UINT otmLineGap; - UINT otmsCapEmHeight; - UINT otmsXHeight; - RECT otmrcFontBox; - int otmMacAscent; - int otmMacDescent; - UINT otmMacLineGap; - UINT otmusMinimumPPEM; - POINT otmptSubscriptSize; - POINT otmptSubscriptOffset; - POINT otmptSuperscriptSize; - POINT otmptSuperscriptOffset; - UINT otmsStrikeoutSize; - int otmsStrikeoutPosition; - int otmsUnderscoreSize; - int otmsUnderscorePosition; - PSTR otmpFamilyName; - PSTR otmpFaceName; - PSTR otmpStyleName; - PSTR otmpFullName; +struct OUTLINETEXTMETRICW { + UINT otmSize; + TEXTMETRIC otmTextMetrics; + BYTE otmFiller; + PANOSE otmPanoseNumber; + UINT otmfsSelection; + UINT otmfsType; + int otmsCharSlopeRise; + int otmsCharSlopeRun; + int otmItalicAngle; + UINT otmEMSquare; + int otmAscent; + int otmDescent; + UINT otmLineGap; + UINT otmsCapEmHeight; + UINT otmsXHeight; + RECT otmrcFontBox; + int otmMacAscent; + int otmMacDescent; + UINT otmMacLineGap; + UINT otmusMinimumPPEM; + POINT otmptSubscriptSize; + POINT otmptSubscriptOffset; + POINT otmptSuperscriptSize; + POINT otmptSuperscriptOffset; + UINT otmsStrikeoutSize; + int otmsStrikeoutPosition; + int otmsUnderscoreSize; + int otmsUnderscorePosition; + PSTR otmpFamilyName; + PSTR otmpFaceName; + PSTR otmpStyleName; + PSTR otmpFullName; } alias OUTLINETEXTMETRIC* LPOUTLINETEXTMETRIC; alias OUTLINETEXTMETRIC _OUTLINETEXTMETRIC; alias OUTLINETEXTMETRIC TOUTLINETEXTMETRIC; alias OUTLINETEXTMETRIC* POUTLINETEXTMETRIC; +version(ANSI){ + alias OUTLINETEXTMETRICA OUTLINETEXTMETRIC; + alias OUTLINETEXTMETRICA* LPOUTLINETEXTMETRICA; +}else { + alias OUTLINETEXTMETRICW OUTLINETEXTMETRIC; + alias OUTLINETEXTMETRICW* LPOUTLINETEXTMETRICW; +} struct OVERLAPPED { @@ -12613,6 +12619,7 @@ UINT flags; } +alias TC_HITTESTINFO TCHITTESTINFO; alias TC_HITTESTINFO _TC_HITTESTINFO; alias TC_HITTESTINFO TTCHITTESTINFO; alias TC_HITTESTINFO* PTCHITTESTINFO; @@ -15855,6 +15862,82 @@ // alias WNDCLASSW WNDCLASS_T; // } +enum TF_DA_COLORTYPE { + TF_CT_NONE = 0, + TF_CT_SYSCOLOR = 1, + TF_CT_COLORREF = 2 +} + +enum TF_DA_LINESTYLE { + TF_LS_NONE = 0, + TF_LS_SOLID = 1, + TF_LS_DOT = 2, + TF_LS_DASH = 3, + TF_LS_SQUIGGLE = 4 +} + +enum TF_DA_ATTR_INFO { + TF_ATTR_INPUT = 0, + TF_ATTR_TARGET_CONVERTED = 1, + TF_ATTR_CONVERTED = 2, + TF_ATTR_TARGET_NOTCONVERTED = 3, + TF_ATTR_INPUT_ERROR = 4, + TF_ATTR_FIXEDCONVERTED = 5, + TF_ATTR_OTHER = -1 +} + +struct TF_DA_COLOR { + TF_DA_COLORTYPE type; + union { + int nIndex; + COLORREF cr; + }; +} + +struct TF_DISPLAYATTRIBUTE{ + TF_DA_COLOR crText; + TF_DA_COLOR crBk; + TF_DA_LINESTYLE lsStyle; + BOOL fBoldLine; + TF_DA_COLOR crLine; + TF_DA_ATTR_INFO bAttr; +} + +struct NMTTCUSTOMDRAW { + NMCUSTOMDRAW nmcd; + UINT uDrawFlags; +} +alias NMTTCUSTOMDRAW* LPNMTTCUSTOMDRAW; + +struct SHDRAGIMAGE { + SIZE sizeDragImage; + POINT ptOffset; + HBITMAP hbmpDragImage; + COLORREF crColorKey; +} + +const CCHILDREN_SCROLLBAR = 5; +struct SCROLLBARINFO { + DWORD cbSize; + RECT rcScrollBar; + int dxyLineButton; + int xyThumbTop; + int xyThumbBottom; + int reserved; + DWORD rgstate[CCHILDREN_SCROLLBAR+1]; +} +alias SCROLLBARINFO* PSCROLLBARINFO; + +struct NMTREEVIEW { + NMHDR hdr; + UINT action; + TVITEM itemOld; + TVITEM itemNew; + POINT ptDrag; +} +alias NMTREEVIEW* PNMTREEVIEW; +alias NMTREEVIEW* LPNMTREEVIEW; + } // end of extern(Windows) diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/layout/RowLayout.d --- a/dwt/layout/RowLayout.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/layout/RowLayout.d Sat May 17 17:34:28 2008 +0200 @@ -138,6 +138,17 @@ public bool fill = false; /** + * center specifies whether the controls in a row should be + * centered vertically in each cell for horizontal layouts, + * or centered horizontally in each cell for vertical layouts. + * + * The default value is false. + * + * @since 3.4 + */ + public bool center = false; + + /** * justify specifies whether the controls in a row should be * fully justified, with any extra space placed between the controls. * @@ -268,7 +279,7 @@ int [] wraps = null; bool wrapped = false; Rectangle [] bounds = null; - if (move && (justify || fill)) { + if (move && (justify || fill || center)) { bounds = new Rectangle [count]; wraps = new int [count]; } @@ -282,17 +293,17 @@ } if (wrap && (i !is 0) && (x + childWidth > width)) { wrapped = true; - if (move && (justify || fill)) wraps [i - 1] = maxHeight; + if (move && (justify || fill || center)) wraps [i - 1] = maxHeight; x = marginLeft + marginWidth; y += spacing + maxHeight; if (pack) maxHeight = 0; } - if (pack || fill) { + if (pack || fill || center) { maxHeight = Math.max (maxHeight, childHeight); } if (move) { int childX = x + clientX, childY = y + clientY; - if (justify || fill) { + if (justify || fill || center) { bounds [i] = new Rectangle (childX, childY, childWidth, childHeight); } else { child.setBounds (childX, childY, childWidth, childHeight); @@ -303,13 +314,13 @@ } maxX = Math.max (clientX + marginLeft + marginWidth, maxX - spacing); if (!wrapped) maxX += marginRight + marginWidth; - if (move && (justify || fill)) { + if (move && (justify || fill || center)) { int space = 0, margin = 0; if (!wrapped) { space = Math.max (0, (width - maxX) / (count + 1)); margin = Math.max (0, ((width - maxX) % (count + 1)) / 2); } else { - if (fill || justify) { + if (fill || justify || center) { int last = 0; if (count > 0) wraps [count - 1] = maxHeight; for (int i=0; i height)) { wrapped = true; - if (move && (justify || fill)) wraps [i - 1] = maxWidth; + if (move && (justify || fill || center)) wraps [i - 1] = maxWidth; x += spacing + maxWidth; y = marginTop + marginHeight; if (pack) maxWidth = 0; } - if (pack || fill) { + if (pack || fill || center) { maxWidth = Math.max (maxWidth, childWidth); } if (move) { int childX = x + clientX, childY = y + clientY; - if (justify || fill) { + if (justify || fill || center) { bounds [i] = new Rectangle (childX, childY, childWidth, childHeight); } else { child.setBounds (childX, childY, childWidth, childHeight); @@ -410,13 +433,13 @@ } maxY = Math.max (clientY + marginTop + marginHeight, maxY - spacing); if (!wrapped) maxY += marginBottom + marginHeight; - if (move && (justify || fill)) { + if (move && (justify || fill || center)) { int space = 0, margin = 0; if (!wrapped) { space = Math.max (0, (height - maxY) / (count + 1)); margin = Math.max (0, ((height - maxY) % (count + 1)) / 2); } else { - if (fill || justify) { + if (fill || justify || center) { int last = 0; if (count > 0) wraps [count - 1] = maxWidth; for (int i=0; i - *
      ALL_PAGES
      + *
      PrinterData.ALL_PAGES
      *
      Print all pages in the current document
      - *
      PAGE_RANGE
      + *
      PrinterData.PAGE_RANGE
      *
      Print the range of pages specified by startPage and endPage
      - *
      SELECTION
      + *
      PrinterData.SELECTION
      *
      Print the current selection
      * * @@ -120,11 +145,11 @@ * setting when the dialog is opened. This can have one of * the following values: *
      - *
      ALL_PAGES
      + *
      PrinterData.ALL_PAGES
      *
      Print all pages in the current document
      - *
      PAGE_RANGE
      + *
      PrinterData.PAGE_RANGE
      *
      Print the range of pages specified by startPage and endPage
      - *
      SELECTION
      + *
      PrinterData.SELECTION
      *
      Print the current selection
      *
      * @@ -139,7 +164,7 @@ * before pressing OK in the dialog. *

      * This value can be from 1 to the maximum number of pages for the platform. - * Note that it is only valid if the scope is PAGE_RANGE. + * Note that it is only valid if the scope is PrinterData.PAGE_RANGE. *

      * * @return the start page setting that the user selected @@ -153,7 +178,7 @@ * is opened. *

      * This value can be from 1 to the maximum number of pages for the platform. - * Note that it is only valid if the scope is PAGE_RANGE. + * Note that it is only valid if the scope is PrinterData.PAGE_RANGE. *

      * * @param startPage the startPage setting when the dialog is opened @@ -167,7 +192,7 @@ * before pressing OK in the dialog. *

      * This value can be from 1 to the maximum number of pages for the platform. - * Note that it is only valid if the scope is PAGE_RANGE. + * Note that it is only valid if the scope is PrinterData.PAGE_RANGE. *

      * * @return the end page setting that the user selected @@ -181,7 +206,7 @@ * is opened. *

      * This value can be from 1 to the maximum number of pages for the platform. - * Note that it is only valid if the scope is PAGE_RANGE. + * Note that it is only valid if the scope is PrinterData.PAGE_RANGE. *

      * * @param endPage the end page setting when the dialog is opened @@ -234,6 +259,17 @@ pd.lStructSize = PRINTDLG.sizeof; Control parent = getParent(); if (parent !is null) pd.hwndOwner = parent.handle; + void* lpInitData; + auto hHeap = OS.GetProcessHeap(); + if (printerData !is null) { + byte buffer [] = printerData.otherData; + if (buffer !is null && buffer.length !is 0) { + /* If user setup info from a previous print dialog was specified, restore the DEVMODE struct. */ + lpInitData = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, buffer.length); + OS.MoveMemory(lpInitData, buffer.ptr, buffer.length); + pd.hDevMode = lpInitData; + } + } pd.Flags = OS.PD_USEDEVMODECOPIESANDCOLLATE; if (printToFile) pd.Flags |= OS.PD_PRINTTOFILE; switch (scope_) { @@ -328,6 +364,7 @@ data.otherData = new byte[size]; OS.MoveMemory(data.otherData.ptr, ptr, size); OS.GlobalUnlock(hMem); + if (lpInitData !is null) OS.HeapFree(hHeap, 0, lpInitData); endPage = data.endPage; printToFile = data.printToFile; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/printing/Printer.d --- a/dwt/printing/Printer.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/printing/Printer.d Sat May 17 17:34:28 2008 +0200 @@ -18,6 +18,7 @@ import dwt.DWTException; import dwt.graphics.Device; import dwt.graphics.DeviceData; +import dwt.graphics.Font; import dwt.graphics.GCData; import dwt.graphics.Point; import dwt.graphics.Rectangle; @@ -254,7 +255,7 @@ data.style |= DWT.LEFT_TO_RIGHT; } data.device = this; - data.hFont = OS.GetCurrentObject(handle, OS.OBJ_FONT); + data.font = Font.win32_new(this, OS.GetCurrentObject(handle, OS.OBJ_FONT)); isGCCreated = true; } return handle; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/printing/PrinterData.d --- a/dwt/printing/PrinterData.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/printing/PrinterData.d Sat May 17 17:34:28 2008 +0200 @@ -130,6 +130,10 @@ * private, platform-specific data * On Windows, this contains a copy of the DEVMODE struct * returned from the PrintDialog. + * On GTK, this contains a copy of the print_settings and page_setup + * returned from the PrintDialog. + * On OS X Carbon, this contains a copy of the PrintSettings and PageFormat + * returned from the PrintDialog. * This field is not currently used on the X/Window System. */ byte [] otherData; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/program/Program.d --- a/dwt/program/Program.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/program/Program.d Sat May 17 17:34:28 2008 +0200 @@ -42,10 +42,11 @@ TCHAR[] pszOut = NewTCHARs(0, 1024); uint[1] pcchOut; pcchOut[0] = pszOut.length; - int result = OS.AssocQueryString(OS.ASSOCF_NOTRUNCATE, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr); + int flags = OS.ASSOCF_NOTRUNCATE | OS.ASSOCF_INIT_IGNOREUNKNOWN; + int result = OS.AssocQueryString (flags, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr); if (result is OS.E_POINTER) { pszOut = NewTCHARs(0, pcchOut [0]); - result = OS.AssocQueryString(OS.ASSOCF_NOTRUNCATE, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr); + result = OS.AssocQueryString (flags, assocStr, key.ptr, null, pszOut.ptr, pcchOut.ptr); } if (result is 0) { if (!OS.IsWinCE && expand) { @@ -252,13 +253,12 @@ } /** - * Launches the executable associated with the file in - * the operating system. If the file is an executable, - * then the executable is launched. Note that a Display - * must already exist to guarantee that this method returns - * an appropriate result. + * Launches the operating system executable associated with the file or + * URL (http:// or https://). If the file is an executable then the + * executable is launched. Note that a Display must already + * exist to guarantee that this method returns an appropriate result. * - * @param fileName the file or program name + * @param fileName the file or program name or URL (http:// or https://) * @return true if the file is launched, otherwise false * * @exception IllegalArgumentException
        @@ -359,6 +359,12 @@ nIconIndex = Integer.parseInt (iconIndex); } catch (NumberFormatException e) {} } + int length = fileName.length; + if (length !is 0 && fileName.charAt (0) is '\"') { + if (fileName.charAt (length - 1) is '\"') { + fileName = fileName.substring (1, length - 1); + } + } /* Use the character encoding for the default locale */ TCHAR[] lpszFile = StrToTCHARs (0, fileName, true); HICON [1] phiconSmall, phiconLarge; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Button.d --- a/dwt/widgets/Button.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Button.d Sat May 17 17:34:28 2008 +0200 @@ -63,7 +63,7 @@ String text = "", message = ""; Image image, image2, disabledImage; ImageList imageList; - bool ignoreMouse; + bool ignoreMouse, grayed; static const int MARGIN = 4; private static /+const+/ int CHECK_WIDTH, CHECK_HEIGHT; static const int ICON_WIDTH = 128, ICON_HEIGHT = 128; @@ -504,8 +504,36 @@ } override void createHandle () { + /* + * Feature in Windows. When a button is created, + * it clears the UI state for all controls in the + * shell by sending WM_CHANGEUISTATE with UIS_SET, + * UISF_HIDEACCEL and UISF_HIDEFOCUS to the parent. + * This is undocumented and unexpected. The fix + * is to ignore the WM_CHANGEUISTATE, when sent + * from CreateWindowEx(). + */ + parent.state |= IGNORE_WM_CHANGEUISTATE; super.createHandle (); - if ((style & DWT.PUSH) is 0) state |= THEME_BACKGROUND; + parent.state &= ~IGNORE_WM_CHANGEUISTATE; + + /* Set the theme background */ + if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { + /* + * NOTE: On Vista this causes problems when the tab + * key is pressed for push buttons so disable the + * theme background drawing for these widgets for + * now. + */ + if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) { + state |= THEME_BACKGROUND; + } else { + if ((style & (DWT.PUSH | DWT.TOGGLE)) is 0) { + state |= THEME_BACKGROUND; + } + } + } + /* * Bug in Windows. For some reason, the HBRUSH that * is returned from WM_CTRLCOLOR is misaligned when @@ -521,6 +549,23 @@ if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { if ((style & DWT.RADIO) !is 0) state |= DRAW_BACKGROUND; } + + /* + * Feature in Windows. Push buttons draw border around + * the button using the default background color instead + * of using the color provided by WM_CTRLCOLOR. The fix + * is to draw the background in WM_CTRLCOLOR. + * + * NOTE: On Vista this causes problems when the tab key + * is pressed for push buttons so disable the fix for now. + */ + if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { + if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) { + if ((style & (DWT.PUSH | DWT.TOGGLE)) !is 0) { + state |= DRAW_BACKGROUND; + } + } + } } override int defaultBackground () { @@ -625,6 +670,24 @@ } /** + * Returns true if the receiver is grayed, + * and false otherwise. When the widget does not have + * the CHECK style, return false. + * + * @return the grayed state of the checkbox + * + * @exception DWTException
          + *
        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
        • + *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • + *
        + */ +public bool getGrayed () { + checkWidget(); + if ((style & DWT.CHECK) is 0) return false; + return grayed; +} + +/** * Returns the receiver's image if it has one, or null * if it does not. * @@ -682,8 +745,8 @@ public bool getSelection () { checkWidget (); if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return false; - int state = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0); - return (state & OS.BST_CHECKED) !is 0; + int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0); + return flags !is OS.BST_UNCHECKED; } /** @@ -705,8 +768,7 @@ } override bool isTabItem () { - //TEMPORARY CODE - //if ((style & DWT.PUSH) !is 0) return true; + if ((style & DWT.PUSH) !is 0) return isTabGroup (); return super.isTabItem (); } @@ -728,6 +790,20 @@ return CharacterToUpper (key) is CharacterToUpper (mnemonic); } +void printWidget (HWND hwnd, HDC hDC) { + /* + * Bug in Windows. For some reason, PrintWindow() fails + * when it is called on a push button. The fix is to + * detect the failure and use WM_PRINT instead. Note + * that WM_PRINT cannot be used all the time because it + * fails for browser controls when the browser has focus. + */ + if (!OS.PrintWindow (hwnd, hDC, 0)) { + int flags = OS.PRF_CLIENT | OS.PRF_NONCLIENT | OS.PRF_ERASEBKGND | OS.PRF_CHILDREN; + OS.SendMessage (hwnd, OS.WM_PRINT, hDC, flags); + } +} + override void releaseWidget () { super.releaseWidget (); if (imageList !is null) imageList.dispose (); @@ -906,6 +982,30 @@ } /** + * Sets the grayed state of the receiver. This state change + * only applies if the control was created with the DWT.CHECK + * style. + * + * @param grayed the new grayed state + * + * @exception DWTException
          + *
        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
        • + *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • + *
        + */ +public void setGrayed (bool grayed) { + checkWidget (); + if ((style & DWT.CHECK) is 0) return; + this.grayed = grayed; + int /*long*/ flags = OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0); + if (grayed) { + if (flags is OS.BST_CHECKED) updateSelection (OS.BST_INDETERMINATE); + } else { + if (flags is OS.BST_INDETERMINATE) updateSelection (OS.BST_CHECKED); + } +} + +/** * Sets the widget message. When the widget is created * with the style DWT.COMMAND, the message text * is displayed to provide further information for the user. @@ -980,16 +1080,10 @@ checkWidget (); if ((style & (DWT.CHECK | DWT.RADIO | DWT.TOGGLE)) is 0) return; int flags = selected ? OS.BST_CHECKED : OS.BST_UNCHECKED; - /* - * Feature in Windows. When BM_SETCHECK is used - * to set the checked state of a radio or check - * button, it sets the WM_TABSTOP style. This - * is undocumented and unwanted. The fix is - * to save and restore the window style bits. - */ - int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); - OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0); - OS.SetWindowLong (handle, OS.GWL_STYLE, bits); + if ((style & DWT.CHECK) !is 0) { + if (selected && grayed) flags = OS.BST_INDETERMINATE; + } + updateSelection (flags); } /** @@ -1038,6 +1132,35 @@ _setText (string); } +void updateSelection (int flags) { + if (flags !is OS.SendMessage (handle, OS.BM_GETCHECK, 0, 0)) { + /* + * Feature in Windows. When BM_SETCHECK is used + * to set the checked state of a radio or check + * button, it sets the WM_TABSTOP style. This + * is undocumented and unwanted. The fix is + * to save and restore the window style bits. + */ + int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); + if ((style & DWT.CHECK) !is 0) { + if (flags is OS.BST_INDETERMINATE) { + bits &= ~OS.BS_CHECKBOX; + bits |= OS.BS_3STATE; + } else { + bits |= OS.BS_CHECKBOX; + bits &= ~OS.BS_3STATE; + } + if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) { + OS.SetWindowLong (handle, OS.GWL_STYLE, bits); + } + } + OS.SendMessage (handle, OS.BM_SETCHECK, flags, 0); + if (bits !is OS.GetWindowLong (handle, OS.GWL_STYLE)) { + OS.SetWindowLong (handle, OS.GWL_STYLE, bits); + } + } +} + override int widgetStyle () { int bits = super.widgetStyle (); if ((style & DWT.FLAT) !is 0) bits |= OS.BS_FLAT; @@ -1184,7 +1307,7 @@ } if (redraw) { OS.InvalidateRect (handle, null, false); - int code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam); + int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam); return new LRESULT (code); } } @@ -1193,7 +1316,7 @@ } override LRESULT wmCommandChild (int wParam, int lParam) { - int code = wParam >> 16; + int code = OS.HIWORD (wParam); switch (code) { case OS.BN_CLICKED: case OS.BN_DOUBLECLICKED: diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Canvas.d --- a/dwt/widgets/Canvas.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Canvas.d Sat May 17 17:34:28 2008 +0200 @@ -24,6 +24,7 @@ import dwt.widgets.Caret; import dwt.widgets.Control; import dwt.widgets.Display; +import dwt.widgets.IME; import dwt.dwthelper.utils; @@ -53,6 +54,7 @@ alias Composite.windowProc windowProc; Caret caret; + IME ime; /** * Prevents uninitialized instances from being created outside the package. @@ -103,37 +105,6 @@ } /** - * Returns the caret. - *

        - * The caret for the control is automatically hidden - * and shown when the control is painted or resized, - * when focus is gained or lost and when an the control - * is scrolled. To avoid drawing on top of the caret, - * the programmer must hide and show the caret when - * drawing in the window any other time. - *

        - * - * @return the caret - * - * @exception DWTException
          - *
        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
        • - *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • - *
        - */ -public Caret getCaret () { - checkWidget (); - return caret; -} - -override void releaseChildren (bool destroy) { - if (caret !is null) { - caret.release (false); - caret = null; - } - super.releaseChildren (destroy); -} - -/** * Fills the interior of the rectangle specified by the arguments, * with the receiver's background. * @@ -166,6 +137,58 @@ } /** + * Returns the caret. + *

        + * The caret for the control is automatically hidden + * and shown when the control is painted or resized, + * when focus is gained or lost and when an the control + * is scrolled. To avoid drawing on top of the caret, + * the programmer must hide and show the caret when + * drawing in the window any other time. + *

        + * + * @return the caret + * + * @exception DWTException
          + *
        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
        • + *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • + *
        + */ +public Caret getCaret () { + checkWidget (); + return caret; +} + +/** + * Returns the IME. + * + * @return the IME + * + * @exception DWTException
          + *
        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
        • + *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • + *
        + * + * @since 3.4 + */ +public IME getIME () { + checkWidget (); + return ime; +} + +void releaseChildren (bool destroy) { + if (caret !is null) { + caret.release (false); + caret = null; + } + if (ime !is null) { + ime.release (false); + ime = null; + } + super.releaseChildren (destroy); +} + +/** * Scrolls a rectangular area of the receiver by first copying * the source area to the destination and then causing the area * of the source which is not covered by the destination to @@ -296,6 +319,27 @@ super.setFont (font); } +/** + * Sets the receiver's IME. + * + * @param ime the new IME for the receiver, may be null + * + * @exception IllegalArgumentException
          + *
        • ERROR_INVALID_ARGUMENT - if the IME has been disposed
        • + *
        + * @exception DWTException
          + *
        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
        • + *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • + *
        + * + * @since 3.4 + */ +public void setIME (IME ime) { + checkWidget (); + if (ime !is null && ime.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT); + this.ime = ime; +} + override int windowProc (HWND hwnd, int msg, int wParam, int lParam) { if (msg is Display.SWT_RESTORECARET) { if ((state & CANVAS) !is 0) { @@ -309,8 +353,34 @@ return super.windowProc (hwnd, msg, wParam, lParam); } -override LRESULT WM_IME_COMPOSITION (int wParam, int lParam) { - LRESULT result = super.WM_IME_COMPOSITION (wParam, lParam); +override LRESULT WM_CHAR (int wParam, int lParam) { + LRESULT result = super.WM_CHAR (wParam, lParam); + if (result !is null) return result; + if (caret !is null) { + switch (wParam) { + case DWT.DEL: + case DWT.BS: + case DWT.ESC: + break; + default: { + if (OS.GetKeyState (OS.VK_CONTROL) >= 0) { + int value; + if (OS.SystemParametersInfo (OS.SPI_GETMOUSEVANISH, 0, &value, 0)) { + if (value !is 0) OS.SetCursor (null); + } + } + } + } + } + return result; +} + +override LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + if (ime !is null) { + LRESULT result = ime.WM_IME_COMPOSITION (wParam, lParam); + if (result !is null) return result; + } + /* * Bug in Windows. On Korean Windows XP, the IME window * for the Korean Input System (MS-IME 2002) always opens @@ -339,7 +409,23 @@ } } } - return result; + return super.WM_IME_COMPOSITION (wParam, lParam); +} + +override LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) { + if (ime !is null) { + LRESULT result = ime.WM_IME_COMPOSITION_START (wParam, lParam); + if (result !is null) return result; + } + return super.WM_IME_COMPOSITION_START (wParam, lParam); +} + +override LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + if (ime !is null) { + LRESULT result = ime.WM_IME_ENDCOMPOSITION (wParam, lParam); + if (result !is null) return result; + } + return super.WM_IME_ENDCOMPOSITION (wParam, lParam); } override LRESULT WM_INPUTLANGCHANGE (int wParam, int lParam) { @@ -352,11 +438,23 @@ } override LRESULT WM_KILLFOCUS (int wParam, int lParam) { + if (ime !is null) { + LRESULT result = ime.WM_KILLFOCUS (wParam, lParam); + if (result !is null) return result; + } LRESULT result = super.WM_KILLFOCUS (wParam, lParam); if (caret !is null) caret.killFocus (); return result; } +override LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { + if (ime !is null) { + LRESULT result = ime.WM_LBUTTONDOWN (wParam, lParam); + if (result !is null) return result; + } + return super.WM_LBUTTONDOWN (wParam, lParam); +} + override LRESULT WM_SETFOCUS (int wParam, int lParam) { LRESULT result = super.WM_SETFOCUS (wParam, lParam); if (caret !is null) caret.setFocus (); @@ -371,7 +469,7 @@ override LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) { LRESULT result = super.WM_WINDOWPOSCHANGED (wParam, lParam); - if (result !is null) return result; + //if (result !is null) return result; /* * Bug in Windows. When a window with style WS_EX_LAYOUTRTL * that contains a caret is resized, Windows does not move the diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Caret.d --- a/dwt/widgets/Caret.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Caret.d Sat May 17 17:34:28 2008 +0200 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -24,6 +24,7 @@ import dwt.widgets.Widget; import dwt.widgets.Canvas; +import dwt.widgets.IME; import dwt.dwthelper.utils; @@ -122,6 +123,13 @@ if (image !is null) { Rectangle rect = image.getBounds (); return new Rectangle (x, y, rect.width, rect.height); + } else { + if (!OS.IsWinCE && width is 0) { + int buffer; + if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) { + return new Rectangle (x, y, buffer, height); + } + } } return new Rectangle (x, y, width, height); } @@ -206,6 +214,13 @@ if (image !is null) { Rectangle rect = image.getBounds (); return new Point (rect.width, rect.height); + } else { + if (!OS.IsWinCE && width is 0) { + int buffer; + if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) { + return new Point (buffer, height); + } + } } return new Point (width, height); } @@ -275,18 +290,29 @@ POINT ptCurrentPos; if (!OS.GetCaretPos (&ptCurrentPos)) return; auto hwnd = parent.handle; - RECT rect; - OS.GetClientRect (hwnd, &rect); - COMPOSITIONFORM lpCompForm; - lpCompForm.dwStyle = OS.CFS_RECT; - lpCompForm.ptCurrentPos.x = ptCurrentPos.x; - lpCompForm.ptCurrentPos.y = ptCurrentPos.y; - lpCompForm.rcArea.left = rect.left; - lpCompForm.rcArea.right = rect.right; - lpCompForm.rcArea.top = rect.top; - lpCompForm.rcArea.bottom = rect.bottom; auto hIMC = OS.ImmGetContext (hwnd); - OS.ImmSetCompositionWindow (hIMC, &lpCompForm); + IME ime = parent.getIME (); + if (ime !is null && ime.isInlineEnabled ()) { + Point size = getSize (); + CANDIDATEFORM lpCandidate; + lpCandidate.dwStyle = OS.CFS_EXCLUDE; + lpCandidate.ptCurrentPos = ptCurrentPos; + //lpCandidate.rcArea = new RECT (); + OS.SetRect (&lpCandidate.rcArea, ptCurrentPos.x, ptCurrentPos.y, ptCurrentPos.x + size.x, ptCurrentPos.y + size.y); + OS.ImmSetCandidateWindow (hIMC, &lpCandidate); + } else { + RECT rect; + OS.GetClientRect (hwnd, &rect); + COMPOSITIONFORM lpCompForm; + lpCompForm.dwStyle = OS.CFS_RECT; + lpCompForm.ptCurrentPos.x = ptCurrentPos.x; + lpCompForm.ptCurrentPos.y = ptCurrentPos.y; + lpCompForm.rcArea.left = rect.left; + lpCompForm.rcArea.right = rect.right; + lpCompForm.rcArea.top = rect.top; + lpCompForm.rcArea.bottom = rect.bottom; + OS.ImmSetCompositionWindow (hIMC, &lpCompForm); + } OS.ImmReleaseContext (hwnd, hIMC); } @@ -308,6 +334,13 @@ auto hwnd = parent.handle; OS.DestroyCaret (); auto hBitmap = image !is null ? image.handle : null; + int width = this.width; + if (!OS.IsWinCE && image is null && width is 0) { + int buffer; + if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) { + width = buffer; + } + } OS.CreateCaret (hwnd, hBitmap, width, height); OS.SetCaretPos (x, y); OS.ShowCaret (hwnd); @@ -345,8 +378,10 @@ bool samePosition = this.x is x && this.y is y; bool sameExtent = this.width is width && this.height is height; if (samePosition && sameExtent) return; - this.x = x; this.y = y; - this.width = width; this.height = height; + this.x = x; + this.y = y; + this.width = width; + this.height = height; if (sameExtent) { moved = true; if (isVisible_ && hasFocus ()) move (); @@ -378,6 +413,13 @@ auto hwnd = parent.handle; HBITMAP hBitmap; if (image !is null) hBitmap = image.handle; + int width = this.width; + if (!OS.IsWinCE && image is null && width is 0) { + int buffer; + if (OS.SystemParametersInfo (OS.SPI_GETCARETWIDTH, 0, &buffer, 0)) { + width = buffer; + } + } OS.CreateCaret (hwnd, hBitmap, width, height); move (); setIMEFont (); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/ColorDialog.d --- a/dwt/widgets/ColorDialog.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/ColorDialog.d Sat May 17 17:34:28 2008 +0200 @@ -65,7 +65,7 @@ * @see Widget#getStyle */ public this (Shell parent) { - this (parent, DWT.PRIMARY_MODAL); + this (parent, DWT.APPLICATION_MODAL); } /** @@ -97,7 +97,7 @@ * @see Widget#getStyle */ public this (Shell parent, int style) { - super (parent, style); + super (parent, checkStyle (parent, style)); checkSubclass (); } @@ -165,6 +165,35 @@ /* Get the owner HWND for the dialog */ auto hwndOwner = parent.handle; + auto hwndParent = parent.handle; + + /* + * Feature in Windows. There is no API to set the orientation of a + * color dialog. It is always inherited from the parent. The fix is + * to create a hidden parent and set the orientation in the hidden + * parent for the dialog to inherit. + */ + bool enabled = false; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) { + int dialogOrientation = style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT); + int parentOrientation = parent.style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT); + if (dialogOrientation !is parentOrientation) { + int exStyle = OS.WS_EX_NOINHERITLAYOUT; + if (dialogOrientation is DWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL; + hwndOwner = OS.CreateWindowEx ( + exStyle, + Shell.DialogClass.ptr, + null, + 0, + OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, + hwndParent, + null, + OS.GetModuleHandle (null), + null); + enabled = OS.IsWindowEnabled (hwndParent) !is 0; + if (enabled) OS.EnableWindow (hwndParent, false); + } + } /* Create the CCHookProc */ //Callback callback = new Callback (this, "CCHookProc", 4); //$NON-NLS-1$ @@ -196,10 +225,10 @@ } /* Make the parent shell be temporary modal */ - Shell oldModal = null; + Dialog oldModal = null; if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { - oldModal = display.getModalDialogShell (); - display.setModalDialogShell (parent); + oldModal = display.getModalDialog (); + display.setModalDialog (this); } /* Open the dialog */ @@ -212,7 +241,7 @@ /* Clear the temporary dialog modal parent */ if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { - display.setModalDialogShell (oldModal); + display.setModalDialog (oldModal); } if (success) { @@ -234,6 +263,13 @@ */ // if (lpCustColors !is 0) OS.HeapFree (hHeap, 0, lpCustColors); + /* Destroy the BIDI orientation window */ + if (hwndParent !is hwndOwner) { + if (enabled) OS.EnableWindow (hwndParent, true); + OS.SetActiveWindow (hwndParent); + OS.DestroyWindow (hwndOwner); + } + /* * This code is intentionally commented. On some * platforms, the owner window is repainted right @@ -242,6 +278,7 @@ */ // if (hwndOwner !is 0) OS.UpdateWindow (hwndOwner); + display = null; if (!success) return null; return rgb; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Combo.d --- a/dwt/widgets/Combo.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Combo.d Sat May 17 17:34:28 2008 +0200 @@ -78,7 +78,7 @@ alias Composite.setToolTipText setToolTipText; private static Combo pThis; - bool noSelection, ignoreDefaultSelection, ignoreCharacter, ignoreModify; + bool noSelection, ignoreDefaultSelection, ignoreCharacter, ignoreModify, ignoreResize; HHOOK cbtHook; int scrollWidth, visibleCount = 5; @@ -321,6 +321,14 @@ override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { if (handle is null) return 0; if (hwnd is handle) { + switch (msg) { + case OS.WM_SIZE: { + ignoreResize = true; + int /*long*/ result = OS.CallWindowProc (ComboProc, hwnd, msg, wParam, lParam); + ignoreResize = false; + return result; + } + } return OS.CallWindowProc( ComboProc, hwnd, msg, wParam, lParam); } auto hwndText = OS.GetDlgItem (handle, CBID_EDIT); @@ -462,8 +470,8 @@ } else { auto hwndText = OS.GetDlgItem (handle, CBID_EDIT); if (hwndText !is null) { - int margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0); - int marginWidth = (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF); + int /*long*/ margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0); + int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins); width += marginWidth + 3; } } @@ -537,11 +545,11 @@ /* Get the text and list window procs */ auto hwndText = OS.GetDlgItem (handle, CBID_EDIT); if (hwndText !is null && EditProc is null) { - EditProc = cast(WNDPROC) OS.GetWindowLong (hwndText, OS.GWL_WNDPROC); + EditProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndText, OS.GWLP_WNDPROC); } auto hwndList = OS.GetDlgItem (handle, CBID_LIST); if (hwndList !is null && ListProc is null) { - ListProc = cast(WNDPROC) OS.GetWindowLong (hwndList, OS.GWL_WNDPROC); + ListProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndList, OS.GWLP_WNDPROC); } /* @@ -638,8 +646,8 @@ int start, end; OS.SendMessage (handle, OS.CB_GETEDITSEL, &start, &end); if (start !is end ) { - int lParam = (x & 0xFFFF) | ((y << 16) & 0xFFFF0000); - int position = OS.SendMessage (hwndText, OS.EM_CHARFROMPOS, 0, lParam) & 0xFFFF; + int /*long*/ lParam = OS.MAKELPARAM (x, y); + int position = OS.LOWORD (OS.SendMessage (hwndText, OS.EM_CHARFROMPOS, 0, lParam)); if (start <= position && position < end ) { if (super.dragDetect (hwnd, x, y, filter, detect, consume)) { if (consume !is null) consume [0] = true; @@ -759,9 +767,9 @@ *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • *
      * - * @since 3.3 + * @since 3.4 */ -/*public*/ bool getListVisible () { +public bool getListVisible () { checkWidget (); if ((style & DWT.DROP_DOWN) !is 0) { return OS.SendMessage (handle, OS.CB_GETDROPPEDSTATE, 0, 0) !is 0; @@ -774,6 +782,29 @@ } /** + * Marks the receiver's list as visible if the argument is true, + * and marks it invisible otherwise. + *

      + * If one of the receiver's ancestors is not visible or some + * other condition makes the receiver not visible, marking + * it visible may not actually cause it to be displayed. + *

      + * + * @param visible the new visibility state + * + * @exception DWTException
        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @since 3.4 + */ +public void setListVisible (bool visible) { + checkWidget (); + OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, visible ? 1 : 0, 0); +} + +/** * Returns the orientation of the receiver. * * @return the orientation style @@ -1570,29 +1601,6 @@ } /** - * Marks the receiver's list as visible if the argument is true, - * and marks it invisible otherwise. - *

      - * If one of the receiver's ancestors is not visible or some - * other condition makes the receiver not visible, marking - * it visible may not actually cause it to be displayed. - *

      - * - * @param visible the new visibility state - * - * @exception DWTException
        - *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • - *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • - *
      - * - * @since 3.3 - */ -/*public*/ void setListVisible (bool visible) { - checkWidget (); - OS.SendMessage (handle, OS.CB_SHOWDROPDOWN, visible ? 1 : 0, 0); -} - -/** * Sets the orientation of the receiver, which must be one * of the constants DWT.LEFT_TO_RIGHT or DWT.RIGHT_TO_LEFT. *

      @@ -1778,7 +1786,7 @@ start = wcsToMbcsPos (start); end = wcsToMbcsPos (end); } - int bits = (start & 0xFFFF) | ((end << 16) & 0xFFFF0000); + int /*long*/ bits = OS.MAKELPARAM (start, end); OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, bits); } @@ -1814,7 +1822,7 @@ int limit = LIMIT; auto hwndText = OS.GetDlgItem (handle, CBID_EDIT); if (hwndText !is null) { - limit = OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0); + limit = OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF; } if (string.length > limit) string = string.substring (0, limit); TCHAR* buffer = StrToTCHARz( string ); @@ -1893,11 +1901,11 @@ auto newProc = display.windowProc; auto hwndText = OS.GetDlgItem (handle, CBID_EDIT); if (hwndText !is null) { - OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, newProc); + OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, newProc); } auto hwndList = OS.GetDlgItem (handle, CBID_LIST); if (hwndList !is null) { - OS.SetWindowLong (hwndList, OS.GWL_WNDPROC, newProc); + OS.SetWindowLongPtr (hwndList, OS.GWLP_WNDPROC, newProc); } } @@ -1907,7 +1915,7 @@ * to select an item in the list and escape to close * the combo box. */ - switch (msg.wParam) { + switch ((msg.wParam)) { case OS.VK_RETURN: case OS.VK_ESCAPE: if ((style & DWT.DROP_DOWN) !is 0) { @@ -1944,11 +1952,11 @@ super.unsubclass (); auto hwndText = OS.GetDlgItem (handle, CBID_EDIT); if (hwndText !is null && EditProc !is null) { - OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, cast(int) EditProc); + OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, cast(LONG_PTR)EditProc); } auto hwndList = OS.GetDlgItem (handle, CBID_LIST); if (hwndList !is null && ListProc !is null) { - OS.SetWindowLong (hwndList, OS.GWL_WNDPROC, cast(int) ListProc); + OS.SetWindowLongPtr (hwndList, OS.GWLP_WNDPROC, cast(LONG_PTR)ListProc); } } @@ -2107,7 +2115,7 @@ } override LRESULT WM_GETDLGCODE (int wParam, int lParam) { - int code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam); return new LRESULT (code | OS.DLGC_WANTARROWS); } @@ -2164,6 +2172,16 @@ override LRESULT WM_SIZE (int wParam, int lParam) { /* + * Feature in Windows. When a combo box is resized, + * the size of the drop down rectangle is specified + * using the height and then the combo box resizes + * to be the height of the text field. This causes + * two WM_SIZE messages to be sent and two DWT.Resize + * events to be issued. The fix is to ignore the + * second resize. + */ + if (ignoreResize) return null; + /* * Bug in Windows. If the combo box has the CBS_SIMPLE style, * the list portion of the combo box is not redrawn when the * combo box is resized. The fix is to force a redraw when @@ -2221,7 +2239,7 @@ if (isDisposed ()) return result; if (buffer !is null) { OS.SetWindowText (handle, buffer.ptr); - int bits = (start & 0xFFFF) | ((end << 16) & 0xFFFF0000); + int /*long*/ bits = OS.MAKELPARAM (start, end); OS.SendMessage (handle, OS.CB_SETEDITSEL, 0, bits); if (redraw) setRedraw (true); } @@ -2236,6 +2254,56 @@ return result; } +override LRESULT WM_WINDOWPOSCHANGING (int /*long*/ wParam, int /*long*/ lParam) { + LRESULT result = super.WM_WINDOWPOSCHANGING (wParam, lParam); + if (result !is null) return result; + /* + * Feature in Windows. When a combo box is resized, + * the size of the drop down rectangle is specified + * using the height and then the combo box resizes + * to be the height of the text field. This causes + * sibling windows that intersect with the original + * bounds to redrawn. The fix is to stop the redraw + * using SWP_NOREDRAW and then damage the combo box + * text field and the area in the parent where the + * combo box used to be. + */ + if (OS.IsWinCE) return result; + if (drawCount !is 0) return result; + if (!OS.IsWindowVisible (handle)) return result; + if (ignoreResize) { + WINDOWPOS* lpwp = cast(WINDOWPOS*)lParam; + if ((lpwp.flags & OS.SWP_NOSIZE) is 0) { + lpwp.flags |= OS.SWP_NOREDRAW; + OS.InvalidateRect (handle, null, true); + RECT rect; + OS.GetWindowRect (handle, &rect); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + if (width !is 0 && height !is 0) { + auto hwndParent = parent.handle; + auto hwndChild = OS.GetWindow (hwndParent, OS.GW_CHILD); + OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2); + auto rgn1 = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom); + while (hwndChild !is null) { + if (hwndChild !is handle) { + OS.GetWindowRect (hwndChild, &rect); + OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2); + auto rgn2 = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom); + OS.CombineRgn (rgn1, rgn1, rgn2, OS.RGN_DIFF); + OS.DeleteObject (rgn2); + } + hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT); + } + int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE; + OS.RedrawWindow (hwndParent, null, rgn1, flags); + OS.DeleteObject (rgn1); + } + } + } + return result; +} + override LRESULT wmChar (HWND hwnd, int wParam, int lParam) { if (ignoreCharacter) return null; LRESULT result = super.wmChar (hwnd, wParam, lParam); @@ -2345,7 +2413,7 @@ } override LRESULT wmCommandChild (int wParam, int lParam) { - int code = wParam >> 16; + int code = OS.HIWORD (wParam); switch (code) { case OS.CBN_EDITCHANGE: if (ignoreModify) break; @@ -2429,7 +2497,7 @@ * them to the application. */ ignoreCharacter = true; - int result = callWindowProc (hwnd, OS.WM_IME_CHAR, wParam, lParam); + int /*long*/ result = callWindowProc (hwnd, OS.WM_IME_CHAR, wParam, lParam); MSG msg; int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE; while (OS.PeekMessage (&msg, hwnd, OS.WM_CHAR, OS.WM_CHAR, flags)) { @@ -2472,7 +2540,7 @@ if (result !is null) return result; if ((style & DWT.READ_ONLY) is 0) { if (wParam is OS.VK_DOWN) { - int code = callWindowProc (hwnd, OS.WM_SYSKEYDOWN, wParam, lParam); + int /*long*/ code = callWindowProc (hwnd, OS.WM_SYSKEYDOWN, wParam, lParam); int newSelection = OS.SendMessage (handle, OS.CB_GETCURSEL, 0, 0); if (oldSelection !is newSelection) { sendEvent (DWT.Modify); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Composite.d --- a/dwt/widgets/Composite.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Composite.d Sat May 17 17:34:28 2008 +0200 @@ -31,6 +31,7 @@ import dwt.widgets.Event; import dwt.widgets.ToolTip; import dwt.widgets.Display; +import dwt.widgets.Widget; import dwt.dwthelper.System; import dwt.dwthelper.utils; @@ -67,11 +68,11 @@ public class Composite : Scrollable { + alias Scrollable.setBounds setBounds; alias Scrollable.computeSize computeSize; alias Scrollable.translateMnemonic translateMnemonic; Layout layout_; - HFONT font; WINDOWPOS* [] lpwp; Control [] tabList; int layoutCount, backgroundMode; @@ -211,6 +212,17 @@ } } +void checkComposited () { + if ((state & CANVAS) !is 0) { + if ((style & DWT.TRANSPARENT) !is 0) { + auto hwndParent = parent.handle; + int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE); + bits |= OS.WS_EX_COMPOSITED; + OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, bits); + } + } +} + override protected void checkSubclass () { /* Do nothing - Subclassing is allowed */ } @@ -254,12 +266,75 @@ return new Point (trim.width, trim.height); } +/** + * Copies a rectangular area of the receiver at the specified + * position using the gc. + * + * @param gc the gc where the rectangle is to be filled + * @param x the x coordinate of the rectangle to be filled + * @param y the y coordinate of the rectangle to be filled + * @param width the width of the rectangle to be filled + * @param height the height of the rectangle to be filled + * + * @exception IllegalArgumentException

        + *
      • ERROR_NULL_ARGUMENT - if the gc is null
      • + *
      • ERROR_INVALID_ARGUMENT - if the gc has been disposed
      • + *
      + * @exception DWTException
        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @since 3.4 + */ +/*public*/ void copyArea (GC gc, int x, int y, int width, int height) { + checkWidget (); + if (gc is null) error (DWT.ERROR_NULL_ARGUMENT); + if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + + //XP only, no GDI+ + //#define PW_CLIENTONLY 0x00000001 + //DCOrg() wrong + //topHandle wrong for Tree? + auto hDC = gc.handle; + int nSavedDC = OS.SaveDC (hDC); + OS.IntersectClipRect (hDC, 0, 0, width, height); + + //WRONG PARENT + POINT lpPoint; + auto hwndParent = OS.GetParent (handle); + OS.MapWindowPoints (handle, hwndParent, &lpPoint, 1); + RECT rect; + OS.GetWindowRect (handle, &rect); + POINT lpPoint1, lpPoint2; + x = x + (lpPoint.x - rect.left); + y = y + (lpPoint.y - rect.top); + OS.SetWindowOrgEx (hDC, x, y, &lpPoint1); + OS.SetBrushOrgEx (hDC, x, y, &lpPoint2); + int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); + if ((bits & OS.WS_VISIBLE) is 0) { + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); + } + //NECESSARY? + OS.RedrawWindow (handle, null, null, OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN); + OS.PrintWindow (handle, hDC, 0);//0x00000001); + if ((bits & OS.WS_VISIBLE) is 0) { + OS.DefWindowProc(handle, OS.WM_SETREDRAW, 0, 0); + } + OS.RestoreDC (hDC, nSavedDC); +} + override void createHandle () { super.createHandle (); state |= CANVAS; if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) { state |= THEME_BACKGROUND; } + if ((style & DWT.TRANSPARENT) !is 0) { + int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); + bits |= OS.WS_EX_TRANSPARENT; + OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits); + } } Composite findDeferredControl () { @@ -677,6 +752,26 @@ return true; } +void releaseParent () { + super.releaseParent (); + if ((state & CANVAS) !is 0) { + if ((style & DWT.TRANSPARENT) !is 0) { + auto hwndParent = parent.handle; + auto hwndChild = OS.GetWindow (hwndParent, OS.GW_CHILD); + while (hwndChild !is null) { + if (hwndChild !is handle) { + int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE); + if ((bits & OS.WS_EX_TRANSPARENT) !is 0) return; + } + hwndChild = OS.GetWindow (hwndChild, OS.GW_HWNDNEXT); + } + int bits = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE); + bits &= ~OS.WS_EX_COMPOSITED; + OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, bits); + } + } +} + override void releaseChildren (bool destroy) { Control [] children = _getChildren (); for (int i=0; i Display.RESIZE_LIMIT) { + defer = false; + } + if (!defer && (state & CANVAS) !is 0) { + state &= ~RESIZE_OCCURRED | MOVE_OCCURRED; + state |= RESIZE_DEFERRED | MOVE_DEFERRED; + } + super.setBounds (x, y, width, height, flags, defer); + if (!defer && (state & CANVAS) !is 0) { + bool wasMoved = (state & MOVE_OCCURRED) !is 0; + bool wasResized = (state & RESIZE_OCCURRED) !is 0; + state &= ~(RESIZE_DEFERRED | MOVE_DEFERRED); + if (wasMoved && !isDisposed ()) sendMove (); + if (wasResized && !isDisposed ()) sendResize (); + } +} + override bool setFixedFocus () { checkWidget (); Control [] children = _getChildren (); @@ -923,6 +1036,9 @@ if (resize) { resizeChildren (); } else { + if (display.resizeCount > Display.RESIZE_LIMIT) { + return; + } int count = getChildrenCount (); if (count > 1 && lpwp is null) { lpwp = new WINDOWPOS* [count]; @@ -945,7 +1061,9 @@ } for (int i=0; i= 6 && OS.IsAppThemed ()) { + if ((state & CANVAS)!is 0) { + auto code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); + if (code is OS.HTCLIENT) { + RECT rect; + OS.GetClientRect (handle, &rect); + POINT pt; + pt.x = OS.GET_X_LPARAM (lParam); + pt.y = OS.GET_Y_LPARAM (lParam); + OS.MapWindowPoints (null, handle, &pt, 1); + if (!OS.PtInRect (&rect, pt)) { + int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE; + OS.RedrawWindow (handle, null, null, flags); + } + } + return new LRESULT (code); + } } return result; } override LRESULT WM_PARENTNOTIFY (int wParam, int lParam) { if ((state & CANVAS) !is 0 && (style & DWT.EMBEDDED) !is 0) { - if ((wParam & 0xFFFF) is OS.WM_CREATE) { + if (OS.LOWORD (wParam) is OS.WM_CREATE) { RECT rect; OS.GetClientRect (handle, &rect); resizeEmbeddedHandle ( cast(HANDLE)lParam, rect.right - rect.left, rect.bottom - rect.top); @@ -1152,7 +1309,7 @@ if ((style & DWT.DOUBLE_BUFFERED) !is 0) { if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { if ((style & (DWT.NO_MERGE_PAINTS | DWT.RIGHT_TO_LEFT)) is 0) { - bufferedPaint = true; + if ((style & DWT.TRANSPARENT) is 0) bufferedPaint = true; } } } @@ -1167,17 +1324,12 @@ OS.SetRect (&prcTarget, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom); auto hBufferedPaint = OS.BeginBufferedPaint (hDC, &prcTarget, flags, null, &phdc); GCData data = new GCData (); - if ((OS.GetLayout (hDC) & OS.LAYOUT_RTL) !is 0) { - data.style = DWT.RIGHT_TO_LEFT | DWT.MIRRORED; - } else { - data.style = DWT.LEFT_TO_RIGHT; - } data.device = display; data.foreground = getForegroundPixel (); Control control = findBackgroundControl (); if (control is null) control = this; data.background = control.getBackgroundPixel (); - data.hFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); + data.font = Font.win32_new(display, cast(HANDLE) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0)); data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); if ((style & DWT.NO_BACKGROUND) !is 0) { /* This code is intentionally commented because it may be slow to copy bits from the screen */ @@ -1195,6 +1347,7 @@ event.width = width; event.height = height; sendEvent (DWT.Paint, event); + if (data.focusDrawn && !isDisposed ()) updateUIState (); gc.dispose (); OS.EndBufferedPaint (hBufferedPaint, true); } @@ -1209,7 +1362,7 @@ /* Get the system region for the paint HDC */ HRGN sysRgn; - if ((style & (DWT.NO_MERGE_PAINTS | DWT.DOUBLE_BUFFERED)) !is 0) { + if ((style & (DWT.DOUBLE_BUFFERED | DWT.TRANSPARENT)) !is 0 || (style & DWT.NO_MERGE_PAINTS) !is 0) { sysRgn = OS.CreateRectRgn (0, 0, 0, 0); if (OS.GetRandomRgn (gc.handle, sysRgn, OS.SYSRGN) is 1) { if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) { @@ -1236,7 +1389,7 @@ if (width !is 0 && height !is 0) { GC paintGC = null; Image image = null; - if ((style & DWT.DOUBLE_BUFFERED) !is 0) { + if ((style & (DWT.DOUBLE_BUFFERED | DWT.TRANSPARENT)) !is 0) { image = new Image (display, width, height); paintGC = gc; gc = new GC (image, paintGC.getStyle() & DWT.RIGHT_TO_LEFT); @@ -1245,13 +1398,16 @@ gc.setForeground (getForeground ()); gc.setBackground (getBackground ()); gc.setFont (getFont ()); + if ((style & DWT.TRANSPARENT) !is 0) { + OS.BitBlt (gc.handle, 0, 0, width, height, paintGC.handle, ps.rcPaint.left, ps.rcPaint.top, OS.SRCCOPY); + } OS.OffsetRgn (sysRgn, -ps.rcPaint.left, -ps.rcPaint.top); OS.SelectClipRgn (gc.handle, sysRgn); OS.OffsetRgn (sysRgn, ps.rcPaint.left, ps.rcPaint.top); OS.SetMetaRgn (gc.handle); OS.SetWindowOrgEx (gc.handle, ps.rcPaint.left, ps.rcPaint.top, null); OS.SetBrushOrgEx (gc.handle, ps.rcPaint.left, ps.rcPaint.top, null); - if ((style & DWT.NO_BACKGROUND) !is 0) { + if ((style & (DWT.NO_BACKGROUND | DWT.TRANSPARENT)) !is 0) { /* This code is intentionally commented because it may be slow to copy bits from the screen */ //paintGC.copyArea (image, ps.left, ps.top); } else { @@ -1271,7 +1427,7 @@ for (int i=0; i> 16); + resizeEmbeddedHandle (OS.GetWindow (handle, OS.GW_CHILD), OS.LOWORD (lParam), OS.HIWORD (lParam)); } return result; } @@ -1437,6 +1601,8 @@ /* * Check to see if the command is a system command or * a user menu item that was added to the system menu. + * + * NOTE: This is undocumented. */ if ((wParam & 0xF000) is 0) return result; @@ -1454,7 +1620,7 @@ case OS.SC_VSCROLL: bool showHBar = horizontalBar !is null && horizontalBar.getVisible (); bool showVBar = verticalBar !is null && verticalBar.getVisible (); - int code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_SYSCOMMAND, wParam, lParam); if ((showHBar !is (horizontalBar !is null && horizontalBar.getVisible ())) || (showVBar !is (verticalBar !is null && verticalBar.getVisible ()))) { int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_UPDATENOW; @@ -1472,33 +1638,40 @@ override LRESULT WM_UPDATEUISTATE (int wParam, int lParam) { LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam); if (result !is null) return result; - if ((state & CANVAS) !is 0) OS.InvalidateRect (handle, null, false); + if ((state & CANVAS) !is 0 && hooks (DWT.Paint)) { + OS.InvalidateRect (handle, null, true); + } return result; } LRESULT wmNCPaint (HWND hwnd, int wParam, int lParam) { - if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { - int bits1 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE); - if ((bits1 & OS.WS_EX_CLIENTEDGE) !is 0) { - int code = 0; - int bits2 = OS.GetWindowLong (hwnd, OS.GWL_STYLE); - if ((bits2 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) !is 0) { - code = callWindowProc (hwnd, OS.WM_NCPAINT, wParam, lParam); + LRESULT result = super.wmNCPaint (hwnd, wParam, lParam); + if (result !is null) return result; + auto borderHandle = borderHandle (); + if ((state & CANVAS) !is 0 || (hwnd is borderHandle && handle !is borderHandle)) { + if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { + int bits1 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE); + if ((bits1 & OS.WS_EX_CLIENTEDGE) !is 0) { + int /*long*/ code = 0; + int bits2 = OS.GetWindowLong (hwnd, OS.GWL_STYLE); + if ((bits2 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) !is 0) { + code = callWindowProc (hwnd, OS.WM_NCPAINT, wParam, lParam); + } + auto hDC = OS.GetWindowDC (hwnd); + RECT rect; + OS.GetWindowRect (hwnd, &rect); + rect.right -= rect.left; + rect.bottom -= rect.top; + rect.left = rect.top = 0; + int border = OS.GetSystemMetrics (OS.SM_CXEDGE); + OS.ExcludeClipRect (hDC, border, border, rect.right - border, rect.bottom - border); + OS.DrawThemeBackground (display.hEditTheme (), hDC, OS.EP_EDITTEXT, OS.ETS_NORMAL, &rect, null); + OS.ReleaseDC (hwnd, hDC); + return new LRESULT (code); } - auto hDC = OS.GetWindowDC (hwnd); - RECT rect; - OS.GetWindowRect (hwnd, &rect); - rect.right -= rect.left; - rect.bottom -= rect.top; - rect.left = rect.top = 0; - int border = OS.GetSystemMetrics (OS.SM_CXEDGE); - OS.ExcludeClipRect (hDC, border, border, rect.right - border, rect.bottom - border); - OS.DrawThemeBackground (display.hEditTheme (), hDC, OS.EP_EDITTEXT, OS.ETS_NORMAL, &rect, null); - OS.ReleaseDC (hwnd, hDC); - return new LRESULT (code); } } - return null; + return result; } override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) { @@ -1568,24 +1741,26 @@ if (string !is null) { Shell shell = getShell (); string = Display.withCrLf (string); - int length_ = string.length; - char [] chars = new char [length_ + 1]; - string.getChars (0, length_, chars, 0); - chars[$-1] = 0; // d initialize it to 0xFF, we need to make it null terminated + char [] chars = fixMnemonic (string); /* * Ensure that the orientation of the tool tip matches * the orientation of the control. */ + Widget widget = null; HWND hwnd = cast(HWND)hdr.idFrom; - if (hwnd !is null && ((lpnmtdi.uFlags & OS.TTF_IDISHWND) !is 0)) { - Control control = display.getControl (hwnd); - if (control !is null) { - if ((control.getStyle () & DWT.RIGHT_TO_LEFT) !is 0) { - lpnmtdi.uFlags |= OS.TTF_RTLREADING; - } else { - lpnmtdi.uFlags &= ~OS.TTF_RTLREADING; - } + if ((lpnmtdi.uFlags & OS.TTF_IDISHWND) !is 0) { + widget = display.getControl (hwnd); + } else { + if (hdr.hwndFrom is shell.toolTipHandle || hdr.hwndFrom is shell.balloonTipHandle) { + widget = shell.findToolTip (hdr.idFrom); + } + } + if (widget !is null) { + if ((widget.getStyle () & DWT.RIGHT_TO_LEFT) !is 0) { + lpnmtdi.uFlags |= OS.TTF_RTLREADING; + } else { + lpnmtdi.uFlags &= ~OS.TTF_RTLREADING; } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Control.d --- a/dwt/widgets/Control.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Control.d Sat May 17 17:34:28 2008 +0200 @@ -37,9 +37,11 @@ import dwt.graphics.Image; import dwt.graphics.Point; import dwt.graphics.Rectangle; +import dwt.graphics.Region; import dwt.internal.win32.OS; import dwt.widgets.Widget; import dwt.widgets.Composite; +import dwt.widgets.Dialog; import dwt.widgets.Event; import dwt.widgets.Shell; import dwt.widgets.Menu; @@ -101,6 +103,8 @@ Object layoutData; Accessible accessible; Image backgroundImage; + Region region; + Font font; int drawCount, foreground, background; /** @@ -516,6 +520,10 @@ style &= ~DWT.DOUBLE_BUFFERED; } +void checkComposited () { + /* Do nothing */ +} + bool checkHandle (HWND hwnd) { return hwnd is handle; } @@ -648,7 +656,7 @@ if (handle is null) error (DWT.ERROR_NO_HANDLES); int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); if ((bits & OS.WS_CHILD) !is 0) { - OS.SetWindowLong (handle, OS.GWL_ID, cast(int)handle); + OS.SetWindowLongPtr (handle, OS.GWLP_ID, cast(LONG_PTR)handle); } if (OS.IsDBLocale && hwndParent !is null) { auto hIMC = OS.ImmGetContext (hwndParent); @@ -664,6 +672,7 @@ createHandle (); checkBackground (); checkBuffered (); + checkComposited (); register (); subclass (); setDefaultFont (); @@ -820,7 +829,7 @@ if ((stateMask & DWT.BUTTON3) !is 0) wParam |= OS.MK_RBUTTON; if ((stateMask & DWT.BUTTON4) !is 0) wParam |= OS.MK_XBUTTON1; if ((stateMask & DWT.BUTTON5) !is 0) wParam |= OS.MK_XBUTTON2; - int lParam = (x & 0xFFFF) | ((y << 16) & 0xFFFF0000); + int /*long*/ lParam = OS.MAKELPARAM (x, y); OS.SendMessage (handle, OS.WM_LBUTTONUP, wParam, lParam); } return false; @@ -1246,6 +1255,7 @@ */ public Font getFont () { checkWidget (); + if (font !is null) return font; auto hFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); if (hFont is null) hFont = defaultFont (); return Font.win32_new (display, hFont); @@ -1392,6 +1402,25 @@ } /** + * Returns the region that defines the shape of the control, + * or null if the control has the default shape. + * + * @return the region that defines the shape of the shell (or null) + * + * @exception DWTException
        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @since 3.4 + * + */ +public Region getRegion () { + checkWidget (); + return region; +} + +/** * Returns the receiver's shell. For all controls other than * shells, this simply returns the control's nearest ancestor * shell. Shells return themselves, even if they are children @@ -1547,7 +1576,7 @@ if (control is null) control = this; auto background = control.getBackgroundPixel (); if (background !is OS.GetBkColor (hDC)) data.background = background; - data.hFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0); + data.font = font !is null ? font : Font.win32_new (display, cast(HFONT)OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0)); data.uiState = OS.SendMessage (hwnd, OS.WM_QUERYUISTATE, 0, 0); } return hDC; @@ -1580,9 +1609,12 @@ } bool isActive () { - Shell dialogShell = display.getModalDialogShell (); - if (dialogShell !is null && dialogShell !is getShell ()) { - return false; + Dialog dialog = display.getModalDialog (); + if (dialog !is null) { + Shell dialogShell = dialog.parent; + if (dialogShell !is null && !dialogShell.isDisposed ()) { + if (dialogShell !is getShell ()) return false; + } } Shell shell = null; Shell [] modalShells = display.modalShells; @@ -1696,7 +1728,7 @@ */ // if (!OS.IsWindowVisible (handle)) return false; // int flags = OS.DCX_CACHE | OS.DCX_CLIPCHILDREN | OS.DCX_CLIPSIBLINGS; -// int hDC = OS.GetDCEx (handle, 0, flags); +// int /*long*/ hDC = OS.GetDCEx (handle, 0, flags); // int result = OS.GetClipBox (hDC, new RECT ()); // OS.ReleaseDC (handle, hDC); // return result !is OS.NULLREGION; @@ -1722,7 +1754,7 @@ } int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); if ((bits & OS.WS_TABSTOP) !is 0) return false; - int code = OS.SendMessage (handle, OS.WM_GETDLGCODE, 0, 0); + int /*long*/ code = OS.SendMessage (handle, OS.WM_GETDLGCODE, 0, 0); if ((code & OS.DLGC_STATIC) !is 0) return false; if ((code & OS.DLGC_WANTALLKEYS) !is 0) return false; if ((code & OS.DLGC_WANTARROWS) !is 0) return false; @@ -1936,6 +1968,45 @@ } /** + * Prints the receiver and all children. + * + * @param gc the gc where the drawing occurs + * + * @exception IllegalArgumentException
        + *
      • ERROR_NULL_ARGUMENT - if the gc is null
      • + *
      • ERROR_INVALID_ARGUMENT - if the gc has been disposed
      • + *
      + * @exception DWTException
        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @since 3.4 + */ +public bool print (GC gc) { + checkWidget (); + if (gc is null) error (DWT.ERROR_NULL_ARGUMENT); + if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { + auto topHandle = topHandle (); + int bits = OS.GetWindowLong (topHandle, OS.GWL_STYLE); + if ((bits & OS.WS_VISIBLE) is 0) { + OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 1, 0); + } + printWidget (topHandle, gc.handle); + if ((bits & OS.WS_VISIBLE) is 0) { + OS.DefWindowProc (topHandle, OS.WM_SETREDRAW, 0, 0); + } + return true; + } + return false; +} + +void printWidget (HWND hwnd, HDC hDC) { + OS.PrintWindow (hwnd, hDC, 0); +} + +/** * Causes the entire bounds of the receiver to be marked * as needing to be redrawn. The next time a paint request * is processed, the control will be completely painted, @@ -2070,6 +2141,8 @@ accessible.internal_dispose_Accessible (); } accessible = null; + region = null; + font = null; } /** @@ -2423,6 +2496,14 @@ return true; } +void sendMove () { + sendEvent (DWT.Move); +} + +void sendResize () { + sendEvent (DWT.Resize); +} + void setBackground () { Control control = findBackgroundControl (); if (control is null) control = this; @@ -2552,23 +2633,21 @@ } void setBounds (int x, int y, int width, int height, int flags, bool defer) { + if (findImageControl () !is null) { + if (backgroundImage is null) flags |= OS.SWP_NOCOPYBITS; + } else { + if (OS.GetWindow (handle, OS.GW_CHILD) is null) { + if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { + if (findThemeControl () !is null) flags |= OS.SWP_NOCOPYBITS; + } + } + } auto topHandle_ = topHandle (); if (defer && parent !is null) { forceResize (); - if (OS.GetWindow (handle, OS.GW_CHILD) is null) { - if (findImageControl () !is null) { - flags |= OS.SWP_NOCOPYBITS; - } else { - if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { - if (findThemeControl () !is null) flags |= OS.SWP_NOCOPYBITS; - } - } - } - WINDOWPOS* [] lpwp = parent.lpwp; - if (lpwp is null) { - SetWindowPos (topHandle_, null, x, y, width, height, flags); - } else { + if (parent.lpwp !is null) { int index = 0; + auto lpwp = parent.lpwp; while (index < lpwp.length) { if (lpwp [index] is null) break; index ++; @@ -2586,10 +2665,10 @@ wp.cy = height; wp.flags = flags; lpwp [index] = wp; + return; } - } else { - SetWindowPos (topHandle_, null, x, y, width, height, flags); } + SetWindowPos (topHandle_, null, x, y, width, height, flags); } /** @@ -2619,7 +2698,8 @@ /** * If the argument is true, causes the receiver to have * all mouse events delivered to it until the method is called with - * false as the argument. + * false as the argument. Note that on some platforms, + * a mouse button must currently be down for capture to be assigned. * * @param capture true to capture the mouse, and false to release it * @@ -2640,7 +2720,7 @@ } void setCursor () { - int lParam = OS.HTCLIENT | (OS.WM_MOUSEMOVE << 16); + int /*long*/ lParam = OS.MAKELPARAM (OS.HTCLIENT, OS.WM_MOUSEMOVE); OS.SendMessage (handle, OS.WM_SETCURSOR, handle, lParam); } @@ -2668,7 +2748,7 @@ if (cursor !is null && cursor.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); this.cursor = cursor; static if (OS.IsWinCE) { - int hCursor = cursor !is null ? cursor.handle : 0; + int /*long*/ hCursor = cursor !is null ? cursor.handle : 0; OS.SetCursor (hCursor); return; } @@ -2797,6 +2877,7 @@ if (font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); hFont = font.handle; } + this.font = font; if (hFont is null) hFont = defaultFont (); OS.SendMessage (handle, OS.WM_SETFONT, hFont, 1); } @@ -3010,6 +3091,36 @@ } } +/** + * Sets the shape of the control to the region specified + * by the argument. When the argument is null, the + * default shape of the control is restored. + * + * @param region the region that defines the shape of the control (or null) + * + * @exception IllegalArgumentException
        + *
      • ERROR_INVALID_ARGUMENT - if the region has been disposed
      • + *
      + * @exception DWTException
        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @since 3.4 + * + */ +public void setRegion (Region region) { + checkWidget (); + if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT); + HRGN hRegion; + if (region !is null) { + hRegion = OS.CreateRectRgn (0, 0, 0, 0); + OS.CombineRgn (hRegion, region.handle, hRegion, OS.RGN_OR); + } + OS.SetWindowRgn (handle, hRegion, true); + this.region = region; +} + bool setSavedFocus () { return forceFocus (); } @@ -3164,10 +3275,10 @@ } void subclass () { - int oldProc = windowProc (); + int /*long*/ oldProc = windowProc (); int newProc = display.windowProc(); if (oldProc is newProc) return; - OS.SetWindowLong (handle, OS.GWL_WNDPROC, newProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, newProc); } /** @@ -3281,7 +3392,7 @@ if (msg.wParam < 0x20) return false; auto hwnd = msg.hwnd; if (OS.GetKeyState (OS.VK_MENU) >= 0) { - int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); + int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); if ((code & OS.DLGC_WANTALLKEYS) !is 0) return false; if ((code & OS.DLGC_BUTTON) is 0) return false; } @@ -3313,7 +3424,7 @@ case OS.VK_ESCAPE: { all = true; lastAscii = 27; - int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); + int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); if ((code & OS.DLGC_WANTALLKEYS) !is 0) { /* * Use DLGC_HASSETSEL to determine that the control @@ -3330,7 +3441,7 @@ case OS.VK_RETURN: { all = true; lastAscii = '\r'; - int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); + int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); if ((code & OS.DLGC_WANTALLKEYS) !is 0) doit = false; detail = DWT.TRAVERSE_RETURN; break; @@ -3338,7 +3449,7 @@ case OS.VK_TAB: { lastAscii = '\t'; bool next = OS.GetKeyState (OS.VK_SHIFT) >= 0; - int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); + int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); if ((code & (OS.DLGC_WANTTAB | OS.DLGC_WANTALLKEYS)) !is 0) { /* * Use DLGC_HASSETSEL to determine that the control is a @@ -3356,9 +3467,6 @@ doit = false; } } - if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) { - if (key is OS.VK_LEFT || key is OS.VK_RIGHT) next = !next; - } detail = next ? DWT.TRAVERSE_TAB_NEXT : DWT.TRAVERSE_TAB_PREVIOUS; break; } @@ -3375,9 +3483,12 @@ if (key is OS.VK_LEFT || key is OS.VK_RIGHT) return false; } lastVirtual = true; - int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); + int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); if ((code & (OS.DLGC_WANTARROWS /*| OS.DLGC_WANTALLKEYS*/)) !is 0) doit = false; bool next = key is OS.VK_DOWN || key is OS.VK_RIGHT; + if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) { + if (key is OS.VK_LEFT || key is OS.VK_RIGHT) next = !next; + } detail = next ? DWT.TRAVERSE_ARROW_NEXT : DWT.TRAVERSE_ARROW_PREVIOUS; break; } @@ -3386,7 +3497,7 @@ all = true; lastVirtual = true; if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false; - int code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); + int /*long*/ code = OS.SendMessage (hwnd, OS.WM_GETDLGCODE, 0, 0); if ((code & OS.DLGC_WANTALLKEYS) !is 0) { /* * Use DLGC_HASSETSEL to determine that the control is a @@ -3546,10 +3657,10 @@ } void unsubclass () { - int newProc = windowProc (); - int oldProc = display.windowProc; + int /*long*/ newProc = windowProc (); + int /*long*/ oldProc = display.windowProc; if (oldProc is newProc) return; - OS.SetWindowLong (handle, OS.GWL_WNDPROC, newProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, newProc); } /** @@ -3711,13 +3822,14 @@ abstract String windowClass (); -abstract int windowProc (); +abstract int /*long*/ windowProc (); int windowProc (HWND hwnd, int msg, int wParam, int lParam) { LRESULT result = null; switch (msg) { case OS.WM_ACTIVATE: result = WM_ACTIVATE (wParam, lParam); break; case OS.WM_CAPTURECHANGED: result = WM_CAPTURECHANGED (wParam, lParam); break; + case OS.WM_CHANGEUISTATE: result = WM_CHANGEUISTATE (wParam, lParam); break; case OS.WM_CHAR: result = WM_CHAR (wParam, lParam); break; case OS.WM_CLEAR: result = WM_CLEAR (wParam, lParam); break; case OS.WM_CLOSE: result = WM_CLOSE (wParam, lParam); break; @@ -3744,6 +3856,8 @@ case OS.WM_HSCROLL: result = WM_HSCROLL (wParam, lParam); break; case OS.WM_IME_CHAR: result = WM_IME_CHAR (wParam, lParam); break; case OS.WM_IME_COMPOSITION: result = WM_IME_COMPOSITION (wParam, lParam); break; + case OS.WM_IME_COMPOSITION_START: result = WM_IME_COMPOSITION_START (wParam, lParam); break; + case OS.WM_IME_ENDCOMPOSITION: result = WM_IME_ENDCOMPOSITION (wParam, lParam); break; case OS.WM_INITMENUPOPUP: result = WM_INITMENUPOPUP (wParam, lParam); break; case OS.WM_INPUTLANGCHANGE: result = WM_INPUTLANGCHANGE (wParam, lParam); break; case OS.WM_HOTKEY: result = WM_HOTKEY (wParam, lParam); break; @@ -3810,27 +3924,32 @@ return callWindowProc (hwnd, msg, wParam, lParam); } -LRESULT WM_ACTIVATE (int wParam, int lParam) { +LRESULT WM_ACTIVATE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_CAPTURECHANGED (int wParam, int lParam) { +LRESULT WM_CAPTURECHANGED (int /*long*/ wParam, int /*long*/ lParam) { return wmCaptureChanged (handle, wParam, lParam); } -LRESULT WM_CHAR (int wParam, int lParam) { +LRESULT WM_CHANGEUISTATE (int /*long*/ wParam, int /*long*/ lParam) { + if ((state & IGNORE_WM_CHANGEUISTATE) !is 0) return LRESULT.ZERO; + return null; +} + +LRESULT WM_CHAR (int /*long*/ wParam, int /*long*/ lParam) { return wmChar (handle, wParam, lParam); } -LRESULT WM_CLEAR (int wParam, int lParam) { +LRESULT WM_CLEAR (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_CLOSE (int wParam, int lParam) { +LRESULT WM_CLOSE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_COMMAND (int wParam, int lParam) { +LRESULT WM_COMMAND (int /*long*/ wParam, int /*long*/ lParam) { /* * When the WM_COMMAND message is sent from a * menu, the HWND parameter in LPARAM is zero. @@ -3838,7 +3957,7 @@ if (lParam is 0) { Decorations shell = menuShell (); if (shell.isEnabled ()) { - int id = wParam & 0xFFFF; + int id = OS.LOWORD (wParam); MenuItem item = display.getMenuItem (id); if (item !is null && item.isEnabled ()) { return item.wmCommandChild (wParam, lParam); @@ -3851,11 +3970,11 @@ return control.wmCommandChild (wParam, lParam); } -LRESULT WM_CONTEXTMENU (int wParam, int lParam) { +LRESULT WM_CONTEXTMENU (int /*long*/ wParam, int /*long*/ lParam) { return wmContextMenu (handle, wParam, lParam); } -LRESULT WM_CTLCOLOR (int wParam, int lParam) { +LRESULT WM_CTLCOLOR (int /*long*/ wParam, int /*long*/ lParam) { auto hPalette = display.hPalette; if (hPalette !is null) { OS.SelectPalette ( cast(HPALETTE)wParam, hPalette, false); @@ -3866,15 +3985,15 @@ return control.wmColorChild (wParam, lParam); } -LRESULT WM_CUT (int wParam, int lParam) { +LRESULT WM_CUT (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_DESTROY (int wParam, int lParam) { +LRESULT WM_DESTROY (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_DRAWITEM (int wParam, int lParam) { +LRESULT WM_DRAWITEM (int /*long*/ wParam, int /*long*/ lParam) { DRAWITEMSTRUCT* struct_ = cast(DRAWITEMSTRUCT*)lParam; if (struct_.CtlType is OS.ODT_MENU) { MenuItem item = display.getMenuItem (struct_.itemID); @@ -3886,15 +4005,15 @@ return control.wmDrawChild (wParam, lParam); } -LRESULT WM_ENDSESSION (int wParam, int lParam) { +LRESULT WM_ENDSESSION (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_ENTERIDLE (int wParam, int lParam) { +LRESULT WM_ENTERIDLE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_ERASEBKGND (int wParam, int lParam) { +LRESULT WM_ERASEBKGND (int /*long*/ wParam, int /*long*/ lParam) { if ((state & DRAW_BACKGROUND) !is 0) { if (findImageControl () !is null) return LRESULT.ONE; } @@ -3906,31 +4025,31 @@ return null; } -LRESULT WM_GETDLGCODE (int wParam, int lParam) { +LRESULT WM_GETDLGCODE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_GETFONT (int wParam, int lParam) { +LRESULT WM_GETFONT (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_GETOBJECT (int wParam, int lParam) { +LRESULT WM_GETOBJECT (int /*long*/ wParam, int /*long*/ lParam) { if (accessible !is null) { - int result = accessible.internal_WM_GETOBJECT (wParam, lParam); + int /*long*/ result = accessible.internal_WM_GETOBJECT (wParam, lParam); if (result !is 0) return new LRESULT (result); } return null; } -LRESULT WM_GETMINMAXINFO (int wParam, int lParam) { +LRESULT WM_GETMINMAXINFO (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_HOTKEY (int wParam, int lParam) { +LRESULT WM_HOTKEY (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_HELP (int wParam, int lParam) { +LRESULT WM_HELP (int /*long*/ wParam, int /*long*/ lParam) { static if (OS.IsWinCE) return null; HELPINFO* lphi = cast(HELPINFO*)lParam; Decorations shell = menuShell (); @@ -3961,21 +4080,29 @@ return null; } -LRESULT WM_HSCROLL (int wParam, int lParam) { +LRESULT WM_HSCROLL (int /*long*/ wParam, int /*long*/ lParam) { Control control = display.getControl (cast(HANDLE)lParam); if (control is null) return null; return control.wmScrollChild (wParam, lParam); } -LRESULT WM_IME_CHAR (int wParam, int lParam) { +LRESULT WM_IME_CHAR (int /*long*/ wParam, int /*long*/ lParam) { return wmIMEChar (handle, wParam, lParam); } -LRESULT WM_IME_COMPOSITION (int wParam, int lParam) { +LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + return null; +} + +LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_INITMENUPOPUP (int wParam, int lParam) { +LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + return null; +} + +LRESULT WM_INITMENUPOPUP (int /*long*/ wParam, int /*long*/ lParam) { /* Ignore WM_INITMENUPOPUP for an accelerator */ if (display.accelKeyHit) return null; @@ -3987,7 +4114,7 @@ */ Shell shell = getShell (); Menu oldMenu = shell.activeMenu, newMenu = null; - if ((lParam >> 16) is 0) { + if (OS.HIWORD (lParam) is 0) { newMenu = menuShell ().findMenu (cast(HANDLE)wParam); if (newMenu !is null) newMenu.update (); } @@ -4032,47 +4159,47 @@ return null; } -LRESULT WM_INPUTLANGCHANGE (int wParam, int lParam) { +LRESULT WM_INPUTLANGCHANGE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_KEYDOWN (int wParam, int lParam) { +LRESULT WM_KEYDOWN (int /*long*/ wParam, int /*long*/ lParam) { return wmKeyDown (handle, wParam, lParam); } -LRESULT WM_KEYUP (int wParam, int lParam) { +LRESULT WM_KEYUP (int /*long*/ wParam, int /*long*/ lParam) { return wmKeyUp (handle, wParam, lParam); } -LRESULT WM_KILLFOCUS (int wParam, int lParam) { +LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) { return wmKillFocus (handle, wParam, lParam); } -LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) { +LRESULT WM_LBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) { return wmLButtonDblClk (handle, wParam, lParam); } -LRESULT WM_LBUTTONDOWN (int wParam, int lParam) { +LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { return wmLButtonDown (handle, wParam, lParam); } -LRESULT WM_LBUTTONUP (int wParam, int lParam) { +LRESULT WM_LBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) { return wmLButtonUp (handle, wParam, lParam); } -LRESULT WM_MBUTTONDBLCLK (int wParam, int lParam) { +LRESULT WM_MBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) { return wmMButtonDblClk (handle, wParam, lParam); } -LRESULT WM_MBUTTONDOWN (int wParam, int lParam) { +LRESULT WM_MBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { return wmMButtonDown (handle, wParam, lParam); } -LRESULT WM_MBUTTONUP (int wParam, int lParam) { +LRESULT WM_MBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) { return wmMButtonUp (handle, wParam, lParam); } -LRESULT WM_MEASUREITEM (int wParam, int lParam) { +LRESULT WM_MEASUREITEM (int /*long*/ wParam, int /*long*/ lParam) { MEASUREITEMSTRUCT* struct_ = cast(MEASUREITEMSTRUCT*)lParam;; if (struct_.CtlType is OS.ODT_MENU) { MenuItem item = display.getMenuItem (struct_.itemID); @@ -4085,7 +4212,7 @@ return control.wmMeasureChild (wParam, lParam); } -LRESULT WM_MENUCHAR (int wParam, int lParam) { +LRESULT WM_MENUCHAR (int /*long*/ wParam, int /*long*/ lParam) { /* * Feature in Windows. When the user types Alt+ * and does not match a mnemonic in the System @@ -4094,18 +4221,18 @@ * for Alt+. The fix is to detect the case and * stop Windows from beeping by closing the menu. */ - int type = wParam >> 16; + int type = OS.HIWORD (wParam); if (type is 0 || type is OS.MF_SYSMENU) { display.mnemonicKeyHit = false; - return new LRESULT (OS.MNC_CLOSE << 16); + return new LRESULT (OS.MAKELRESULT (0, OS.MNC_CLOSE)); } return null; } -LRESULT WM_MENUSELECT (int wParam, int lParam) { - int code = wParam >> 16; +LRESULT WM_MENUSELECT (int /*long*/ wParam, int /*long*/ lParam) { + int code = OS.HIWORD (wParam); Shell shell = getShell (); - if (code is -1 && lParam is 0) { + if (code is 0xFFFF && lParam is 0) { Menu menu = shell.activeMenu; while (menu !is null) { /* @@ -4142,7 +4269,7 @@ MenuItem item = null; Decorations menuShell = menuShell (); if ((code & OS.MF_POPUP) !is 0) { - int index = wParam & 0xFFFF; + int index = OS.LOWORD (wParam); MENUITEMINFO info; info.cbSize = MENUITEMINFO.sizeof; info.fMask = OS.MIIM_SUBMENU; @@ -4153,7 +4280,7 @@ } else { Menu newMenu = menuShell.findMenu (cast(HANDLE)lParam); if (newMenu !is null) { - int id = wParam & 0xFFFF; + int id = OS.LOWORD (wParam); item = display.getMenuItem (id); } Menu oldMenu = shell.activeMenu; @@ -4175,6 +4302,7 @@ ancestor.sendEvent (DWT.Hide); if (ancestor.isDisposed ()) break; ancestor = ancestor.getParentMenu (); + if (ancestor is null) break; } /* * The shell and/or the item could be disposed when @@ -4197,28 +4325,29 @@ return null; } -LRESULT WM_MOUSEACTIVATE (int wParam, int lParam) { +LRESULT WM_MOUSEACTIVATE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_MOUSEHOVER (int wParam, int lParam) { +LRESULT WM_MOUSEHOVER (int /*long*/ wParam, int /*long*/ lParam) { return wmMouseHover (handle, wParam, lParam); } -LRESULT WM_MOUSELEAVE (int wParam, int lParam) { +LRESULT WM_MOUSELEAVE (int /*long*/ wParam, int /*long*/ lParam) { if (OS.COMCTL32_MAJOR >= 6) getShell ().fixToolTip (); return wmMouseLeave (handle, wParam, lParam); } -LRESULT WM_MOUSEMOVE (int wParam, int lParam) { +LRESULT WM_MOUSEMOVE (int /*long*/ wParam, int /*long*/ lParam) { return wmMouseMove (handle, wParam, lParam); } -LRESULT WM_MOUSEWHEEL (int wParam, int lParam) { +LRESULT WM_MOUSEWHEEL (int /*long*/ wParam, int /*long*/ lParam) { return wmMouseWheel (handle, wParam, lParam); } -LRESULT WM_MOVE (int wParam, int lParam) { +LRESULT WM_MOVE (int /*long*/ wParam, int /*long*/ lParam) { + state |= MOVE_OCCURRED; if (findImageControl () !is null) { if (this !is getShell ()) redrawChildren (); } else { @@ -4230,88 +4359,88 @@ } } } - sendEvent (DWT.Move); + if ((state & MOVE_DEFERRED) is 0) sendEvent (DWT.Move); // widget could be disposed at this point return null; } -LRESULT WM_NCACTIVATE (int wParam, int lParam) { +LRESULT WM_NCACTIVATE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_NCCALCSIZE (int wParam, int lParam) { +LRESULT WM_NCCALCSIZE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_NCHITTEST (int wParam, int lParam) { +LRESULT WM_NCHITTEST (int /*long*/ wParam, int /*long*/ lParam) { if (!OS.IsWindowEnabled (handle)) return null; if (!isActive ()) return new LRESULT (OS.HTTRANSPARENT); return null; } -LRESULT WM_NCLBUTTONDOWN (int wParam, int lParam) { +LRESULT WM_NCLBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_NCPAINT (int wParam, int lParam) { - return null; -} - -LRESULT WM_NOTIFY (int wParam, int lParam) { +LRESULT WM_NCPAINT (int /*long*/ wParam, int /*long*/ lParam) { + return wmNCPaint (handle, wParam, lParam); +} + +LRESULT WM_NOTIFY (int /*long*/ wParam, int /*long*/ lParam) { NMHDR* hdr = cast(NMHDR*)lParam; return wmNotify (hdr, wParam, lParam); } -LRESULT WM_PAINT (int wParam, int lParam) { - return super.wmPaint (handle, wParam, lParam); -} - -LRESULT WM_PALETTECHANGED (int wParam, int lParam) { +LRESULT WM_PAINT (int /*long*/ wParam, int /*long*/ lParam) { + return wmPaint (handle, wParam, lParam); +} + +LRESULT WM_PALETTECHANGED (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_PARENTNOTIFY (int wParam, int lParam) { +LRESULT WM_PARENTNOTIFY (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_PASTE (int wParam, int lParam) { +LRESULT WM_PASTE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_PRINT (int wParam, int lParam) { +LRESULT WM_PRINT (int /*long*/ wParam, int /*long*/ lParam) { return wmPrint (handle, wParam, lParam); } -LRESULT WM_PRINTCLIENT (int wParam, int lParam) { +LRESULT WM_PRINTCLIENT (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_QUERYENDSESSION (int wParam, int lParam) { +LRESULT WM_QUERYENDSESSION (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_QUERYNEWPALETTE (int wParam, int lParam) { +LRESULT WM_QUERYNEWPALETTE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_QUERYOPEN (int wParam, int lParam) { +LRESULT WM_QUERYOPEN (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_RBUTTONDBLCLK (int wParam, int lParam) { +LRESULT WM_RBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) { return wmRButtonDblClk (handle, wParam, lParam); } -LRESULT WM_RBUTTONDOWN (int wParam, int lParam) { +LRESULT WM_RBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { return wmRButtonDown (handle, wParam, lParam); } -LRESULT WM_RBUTTONUP (int wParam, int lParam) { +LRESULT WM_RBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) { return wmRButtonUp (handle, wParam, lParam); } -LRESULT WM_SETCURSOR (int wParam, int lParam) { - int hitTest = cast(short) (lParam & 0xFFFF); +LRESULT WM_SETCURSOR (int /*long*/ wParam, int /*long*/ lParam) { + int hitTest = cast(short) OS.LOWORD (lParam); if (hitTest is OS.HTCLIENT) { Control control = display.getControl (cast(HANDLE)wParam); if (control is null) return null; @@ -4324,51 +4453,54 @@ return null; } -LRESULT WM_SETFOCUS (int wParam, int lParam) { +LRESULT WM_SETFOCUS (int /*long*/ wParam, int /*long*/ lParam) { return wmSetFocus (handle, wParam, lParam); } -LRESULT WM_SETTINGCHANGE (int wParam, int lParam) { +LRESULT WM_SETTINGCHANGE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_SETFONT (int wParam, int lParam) { +LRESULT WM_SETFONT (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_SETREDRAW (int wParam, int lParam) { +LRESULT WM_SETREDRAW (int /*long*/ wParam, int /*long*/ lParam) { + return null; +} + +LRESULT WM_SHOWWINDOW (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_SHOWWINDOW (int wParam, int lParam) { - return null; -} - -LRESULT WM_SIZE (int wParam, int lParam) { - sendEvent (DWT.Resize); +LRESULT WM_SIZE (int /*long*/ wParam, int /*long*/ lParam) { + state |= RESIZE_OCCURRED; + if ((state & RESIZE_DEFERRED) is 0) sendEvent (DWT.Resize); // widget could be disposed at this point return null; } -LRESULT WM_SYSCHAR (int wParam, int lParam) { +LRESULT WM_SYSCHAR (int /*long*/ wParam, int /*long*/ lParam) { return wmSysChar (handle, wParam, lParam); } -LRESULT WM_SYSCOLORCHANGE (int wParam, int lParam) { +LRESULT WM_SYSCOLORCHANGE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_SYSCOMMAND (int wParam, int lParam) { +LRESULT WM_SYSCOMMAND (int /*long*/ wParam, int /*long*/ lParam) { /* * Check to see if the command is a system command or * a user menu item that was added to the System menu. * When a user item is added to the System menu, * WM_SYSCOMMAND must always return zero. + * + * NOTE: This is undocumented. */ if ((wParam & 0xF000) is 0) { Decorations shell = menuShell (); if (shell.isEnabled ()) { - MenuItem item = display.getMenuItem (wParam & 0xFFFF); + MenuItem item = display.getMenuItem (OS.LOWORD (wParam)); if (item !is null) item.wmCommandChild (wParam, lParam); } return LRESULT.ZERO; @@ -4472,37 +4604,43 @@ return null; } -LRESULT WM_SYSKEYDOWN (int wParam, int lParam) { +LRESULT WM_SYSKEYDOWN (int /*long*/ wParam, int /*long*/ lParam) { return wmSysKeyDown (handle, wParam, lParam); } -LRESULT WM_SYSKEYUP (int wParam, int lParam) { +LRESULT WM_SYSKEYUP (int /*long*/ wParam, int /*long*/ lParam) { return wmSysKeyUp (handle, wParam, lParam); } -LRESULT WM_TIMER (int wParam, int lParam) { +LRESULT WM_TIMER (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_UNDO (int wParam, int lParam) { +LRESULT WM_UNDO (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_UPDATEUISTATE (int wParam, int lParam) { +LRESULT WM_UPDATEUISTATE (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT WM_VSCROLL (int wParam, int lParam) { +LRESULT WM_VSCROLL (int /*long*/ wParam, int /*long*/ lParam) { Control control = display.getControl (cast(HANDLE)lParam); if (control is null) return null; return control.wmScrollChild (wParam, lParam); } -LRESULT WM_WINDOWPOSCHANGED (int wParam, int lParam) { - return null; -} - -LRESULT WM_WINDOWPOSCHANGING (int wParam, int lParam) { +LRESULT WM_WINDOWPOSCHANGED (int /*long*/ wParam, int /*long*/ lParam) { + try { + display.resizeCount++; + int /*long*/ code = callWindowProc (handle, OS.WM_WINDOWPOSCHANGED, wParam, lParam); + return code is 0 ? LRESULT.ZERO : new LRESULT (code); + } finally { + --display.resizeCount; + } +} + +LRESULT WM_WINDOWPOSCHANGING (int /*long*/ wParam, int /*long*/ lParam) { /* * Bug in Windows. When WM_SETREDRAW is used to turn off drawing * for a control and the control is moved or resized, Windows does @@ -4516,28 +4654,42 @@ if ((lpwp.flags & OS.SWP_NOMOVE) is 0 || (lpwp.flags & OS.SWP_NOSIZE) is 0) { RECT rect; OS.GetWindowRect (topHandle (), &rect); - auto hwndParent = parent is null ? null : parent.handle; - OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2); - OS.InvalidateRect (hwndParent, &rect, true); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + if (width !is 0 && height !is 0) { + auto hwndParent = parent is null ? null : parent.handle; + OS.MapWindowPoints (null, hwndParent, cast(POINT*)&rect, 2); + static if (OS.IsWinCE) { + OS.InvalidateRect (hwndParent, &rect, true); + } else { + auto rgn1 = OS.CreateRectRgn (rect.left, rect.top, rect.right, rect.bottom); + auto rgn2 = OS.CreateRectRgn (lpwp.x, lpwp.y, lpwp.x + lpwp.cx, lpwp.y + lpwp.cy); + OS.CombineRgn (rgn1, rgn1, rgn2, OS.RGN_DIFF); + int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN; + OS.RedrawWindow (hwndParent, null, rgn1, flags); + OS.DeleteObject (rgn1); + OS.DeleteObject (rgn2); + } + } } } } return null; } -LRESULT WM_XBUTTONDBLCLK (int wParam, int lParam) { +LRESULT WM_XBUTTONDBLCLK (int /*long*/ wParam, int /*long*/ lParam) { return wmXButtonDblClk (handle, wParam, lParam); } -LRESULT WM_XBUTTONDOWN (int wParam, int lParam) { +LRESULT WM_XBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { return wmXButtonDown (handle, wParam, lParam); } -LRESULT WM_XBUTTONUP (int wParam, int lParam) { +LRESULT WM_XBUTTONUP (int /*long*/ wParam, int /*long*/ lParam) { return wmXButtonUp (handle, wParam, lParam); } -LRESULT wmColorChild (int wParam, int lParam) { +LRESULT wmColorChild (int /*long*/ wParam, int /*long*/ lParam) { Control control = findBackgroundControl (); if (control is null) { if ((state & THEME_BACKGROUND) !is 0) { @@ -4591,15 +4743,15 @@ return new LRESULT ( cast(int) hBrush); } -LRESULT wmCommandChild (int wParam, int lParam) { +LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT wmDrawChild (int wParam, int lParam) { +LRESULT wmDrawChild (int /*long*/ wParam, int /*long*/ lParam) { return null; } -LRESULT wmMeasureChild (int wParam, int lParam) { +LRESULT wmMeasureChild (int /*long*/ wParam, int /*long*/ lParam) { return null; } @@ -4613,7 +4765,7 @@ return null; } -LRESULT wmScrollChild (int wParam, int lParam) { +LRESULT wmScrollChild (int /*long*/ wParam, int /*long*/ lParam) { return null; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/CoolBar.d --- a/dwt/widgets/CoolBar.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/CoolBar.d Sat May 17 17:34:28 2008 +0200 @@ -1102,7 +1102,7 @@ */ if (OS.COMCTL32_MAJOR >= 6) return LRESULT.ZERO; Rectangle rect = getBounds (); - int code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam); OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam); if ( rect != getBounds ()) { parent.redraw (rect.x, rect.y, rect.width, rect.height, true); @@ -1112,7 +1112,7 @@ override LRESULT WM_SIZE (int wParam, int lParam) { if (ignoreResize) { - int code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_SIZE, wParam, lParam); if (code is 0) return LRESULT.ZERO; return new LRESULT (code); } @@ -1130,8 +1130,7 @@ case OS.RBN_BEGINDRAG: { int pos = OS.GetMessagePos (); POINT pt; - pt.x = cast(short) (pos & 0xFFFF); - pt.y = cast(short) (pos >> 16); + OS.POINTSTOPOINT (pt, pos); OS.ScreenToClient (handle, &pt); int button = display.lastButton !is 0 ? display.lastButton : 1; if (!sendDragEvent (button, pt.x, pt.y)) return LRESULT.ONE; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/DateTime.d --- a/dwt/widgets/DateTime.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/DateTime.d Sat May 17 17:34:28 2008 +0200 @@ -13,7 +13,6 @@ module dwt.widgets.DateTime; import dwt.widgets.Composite; - import dwt.DWT; import dwt.DWTException; import dwt.events.SelectionEvent; @@ -26,6 +25,7 @@ import dwt.dwthelper.utils; import Integer = tango.text.convert.Integer; +import tango.text.convert.Format; //TODO - features not yet implemented: read-only, drop-down calendar for date //TODO - font, colors, background image not yet implemented (works on some platforms) @@ -59,6 +59,9 @@ alias Composite.computeSize computeSize; alias Composite.windowProc windowProc; + bool ignoreSelection; + SYSTEMTIME* lastSystemTime; + SYSTEMTIME time; // only used in calendar mode static /+const+/ WNDPROC DateTimeProc; static const TCHAR* DateTimeClass = OS.DATETIMEPICK_CLASS.ptr; static /+const+/ WNDPROC CalendarProc; @@ -356,6 +359,12 @@ override void createHandle () { super.createHandle (); state &= ~(CANVAS | THEME_BACKGROUND); + + if ((style & DWT.BORDER) is 0) { + int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); + bits &= ~(OS.WS_EX_CLIENTEDGE | OS.WS_EX_STATICEDGE); + OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits); + } } override int defaultBackground () { @@ -518,6 +527,7 @@ */ public int getHours () { checkWidget (); + if ((style & DWT.CALENDAR) !is 0) return time.wHour; SYSTEMTIME systime; int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; OS.SendMessage (handle, msg, 0, &systime); @@ -539,6 +549,7 @@ */ public int getMinutes () { checkWidget (); + if ((style & DWT.CALENDAR) !is 0) return time.wMinute; SYSTEMTIME systime; int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; OS.SendMessage (handle, msg, 0, &systime); @@ -567,7 +578,8 @@ } override String getNameText () { - return "DateTime"; + return (style & DWT.TIME) !is 0 ? Format( "{}:{}:{}", getHours(), getMinutes(), getSeconds()) + : Format("{}/{}/{}", (getMonth() + 1), getDay(), getYear()); } /** @@ -585,6 +597,7 @@ */ public int getSeconds () { checkWidget (); + if ((style & DWT.CALENDAR) !is 0) return time.wSecond; SYSTEMTIME systime; int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; OS.SendMessage (handle, msg, 0, &systime); @@ -612,6 +625,11 @@ return systime.wYear; } +void releaseWidget () { + super.releaseWidget (); + lastSystemTime = null; +} + /** * Removes the listener from the collection of listeners who will * be notified when the control is selected by the user. @@ -638,6 +656,37 @@ } /** + * Sets the receiver's year, month, and day in a single operation. + *

      + * This is the recommended way to set the date, because setting the year, + * month, and day separately may result in invalid intermediate dates. + *

      + * + * @param year an integer between 1752 and 9999 + * @param month an integer between 0 and 11 + * @param day a positive integer beginning with 1 + * + * @exception DWTException
        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @since 3.4 + */ +public void setDate (int year, int month, int day) { + checkWidget (); + SYSTEMTIME systime; + int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; + OS.SendMessage (handle, msg, 0, &systime); + msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; + systime.wYear = cast(short)year; + systime.wMonth = cast(short)(month + 1); + systime.wDay = cast(short)day; + OS.SendMessage (handle, msg, 0, &systime); + lastSystemTime = null; +} + +/** * Sets the receiver's date, or day of the month, to the specified day. *

      * The first day of the month is 1, and the last day depends on the month and year. @@ -658,6 +707,7 @@ msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; systime.wDay = cast(short)day; OS.SendMessage (handle, msg, 0, &systime); + lastSystemTime = null; } /** @@ -681,6 +731,7 @@ msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; systime.wHour = cast(short)hours; OS.SendMessage (handle, msg, 0, &systime); + if ((style & DWT.CALENDAR) !is 0 && hours >= 0 && hours <= 23) time.wHour = cast(short)hours; } /** @@ -704,6 +755,7 @@ msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; systime.wMinute = cast(short)minutes; OS.SendMessage (handle, msg, 0, &systime); + if ((style & DWT.CALENDAR) !is 0 && minutes >= 0 && minutes <= 59) time.wMinute = cast(short)minutes; } /** @@ -727,6 +779,7 @@ msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; systime.wMonth = cast(short)(month + 1); OS.SendMessage (handle, msg, 0, &systime); + lastSystemTime = null; } /** @@ -750,6 +803,41 @@ msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; systime.wSecond = cast(short)seconds; OS.SendMessage (handle, msg, 0, &systime); + if ((style & DWT.CALENDAR) !is 0 && seconds >= 0 && seconds <= 59) time.wSecond = cast(short)seconds; +} + +/** + * Sets the receiver's hours, minutes, and seconds in a single operation. + * + * @param hours an integer between 0 and 23 + * @param minutes an integer between 0 and 59 + * @param seconds an integer between 0 and 59 + * + * @exception DWTException

        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @since 3.4 + */ +public void setTime (int hours, int minutes, int seconds) { + checkWidget (); + SYSTEMTIME systime; + int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; + OS.SendMessage (handle, msg, 0, &systime); + msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; + systime.wHour = cast(short)hours; + systime.wMinute = cast(short)minutes; + systime.wSecond = cast(short)seconds; + OS.SendMessage (handle, msg, 0, &systime); + if ((style & DWT.CALENDAR) !is 0 + && hours >= 0 && hours <= 23 + && minutes >= 0 && minutes <= 59 + && seconds >= 0 && seconds <= 59) { + time.wHour = cast(short)hours; + time.wMinute = cast(short)minutes; + time.wSecond = cast(short)seconds; + } } /** @@ -773,6 +861,7 @@ msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_SETCURSEL : OS.DTM_SETSYSTEMTIME; systime.wYear = cast(short)year; OS.SendMessage (handle, msg, 0, &systime); + lastSystemTime = null; } override int widgetStyle () { @@ -799,13 +888,37 @@ override LRESULT wmNotifyChild (NMHDR* hdr, int wParam, int lParam) { switch (hdr.code) { - case OS.MCN_SELCHANGE: //SENT WHEN YOU SET IT? + case OS.MCN_SELCHANGE: case OS.DTN_DATETIMECHANGE: - sendEvent (DWT.Selection); + if (ignoreSelection) break; + SYSTEMTIME systime; + int msg = (style & DWT.CALENDAR) !is 0 ? OS.MCM_GETCURSEL : OS.DTM_GETSYSTEMTIME; + OS.SendMessage (handle, msg, 0, &systime); + if (lastSystemTime is null || systime.wDay !is lastSystemTime.wDay || systime.wMonth !is lastSystemTime.wMonth || systime.wYear !is lastSystemTime.wYear) { + postEvent (DWT.Selection); + if ((style & DWT.TIME) is 0) { + lastSystemTime = new SYSTEMTIME(); + *lastSystemTime = systime; + } + } break; default: } return super.wmNotifyChild (hdr, wParam, lParam); } + +LRESULT WM_TIMER (int /*long*/ wParam, int /*long*/ lParam) { + LRESULT result = super.WM_TIMER (wParam, lParam); + if (result !is null) return result; + /* + * Feature in Windows. For some reason, Windows sends WM_NOTIFY with + * MCN_SELCHANGE at regular intervals. This is unexpected. The fix is + * to ignore MCN_SELCHANGE during WM_TIMER. + */ + ignoreSelection = true; + int /*long*/ code = callWindowProc(handle, OS.WM_TIMER, wParam, lParam); + ignoreSelection = false; + return code is 0 ? LRESULT.ZERO : new LRESULT(code); +} } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Decorations.d --- a/dwt/widgets/Decorations.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Decorations.d Sat May 17 17:34:28 2008 +0200 @@ -310,6 +310,10 @@ /* Do nothing */ } +void checkComposited (Composite parent) { + /* Do nothing */ +} + override void checkOpened () { if (!opened) resized = false; } @@ -412,8 +416,7 @@ while (menu !is null && menu !is menuBar) { menu = menu.getParentMenu (); } - if (menu is menuBar) { - item.fillAccel (&accel); + if (menu is menuBar && item.fillAccel (&accel)) { *cast(ACCEL*)buffer1.ptr = accel; //OS.MoveMemory (buffer1, accel, ACCEL.sizeof); System.arraycopy (buffer1, 0, buffer2, nAccel * ACCEL.sizeof, ACCEL.sizeof); @@ -1218,7 +1221,7 @@ int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); bits &= ~OS.WS_CHILD; OS.SetWindowLong (handle, OS.GWL_STYLE, bits | OS.WS_POPUP); - OS.SetWindowLong (handle, OS.GWL_ID, 0); + OS.SetWindowLongPtr (handle, OS.GWLP_ID, 0); int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; SetWindowPos (handle, cast(HWND)OS.HWND_BOTTOM, 0, 0, 0, 0, flags); display.lockActiveWindow = false; @@ -1337,7 +1340,18 @@ checkWidget (); if (string is null) error (DWT.ERROR_NULL_ARGUMENT); /* Use the character encoding for the default locale */ - OS.SetWindowText (handle, StrToTCHARz(string)); + TCHAR[] buffer = StrToTCHARs (string, true); + /* Ensure that the title appears in the task bar.*/ + if ((state & FOREIGN_HANDLE) !is 0) { + auto hHeap = OS.GetProcessHeap (); + int byteCount = buffer.length * TCHAR.sizeof; + auto pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); + OS.MoveMemory (pszText, buffer.ptr, byteCount); + OS.DefWindowProc (handle, OS.WM_SETTEXT, 0, cast(int) pszText); + if (pszText !is null) OS.HeapFree (hHeap, 0, pszText); + } else { + OS.SetWindowText (handle, buffer.ptr); + } } override public void setVisible (bool visible) { @@ -1402,11 +1416,7 @@ if (OS.IsZoomed (handle)) { swFlags = OS.SW_SHOWMAXIMIZED; } else { - if (handle is OS.GetActiveWindow ()) { - swFlags = OS.SW_RESTORE; - } else { - swFlags = OS.SW_SHOWNOACTIVATE; - } + swFlags = OS.SW_SHOWNOACTIVATE; } } } @@ -1462,7 +1472,7 @@ } if (msg.message is OS.WM_KEYDOWN) { if (OS.GetKeyState (OS.VK_CONTROL) >= 0) return false; - switch (msg.wParam) { + switch ((msg.wParam)) { case OS.VK_F4: OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); return true; @@ -1473,7 +1483,7 @@ return false; } if (msg.message is OS.WM_SYSKEYDOWN) { - switch (msg.wParam) { + switch ((msg.wParam)) { case OS.VK_F4: OS.PostMessage (shell.handle, OS.WM_CLOSE, 0, 0); return true; @@ -1612,14 +1622,14 @@ return LRESULT.ZERO; } } - if ((wParam & 0xFFFF) !is 0) { + if (OS.LOWORD (wParam) !is 0) { /* * When the high word of wParam is non-zero, the activation * state of the window is being changed while the window is * minimized. If this is the case, do not report activation * events or restore the focus. */ - if ((wParam >> 16) !is 0) return result; + if (OS.HIWORD (wParam) !is 0) return result; Control control = display.findControl (cast(HWND)lParam); if (control is null || (null !is cast(Shell)control)) { if (cast(Shell)this) { @@ -1672,7 +1682,7 @@ * If the Shell has the DWT.CLOSE style, close the Shell. * Otherwise, send the Back key to the window with focus. */ - if (((lParam >> 16) & 0xFFFF) is OS.VK_ESCAPE) { + if (OS.HIWORD (lParam) is OS.VK_ESCAPE) { if ((style & DWT.CLOSE) !is 0) { OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); } else { @@ -1751,8 +1761,8 @@ switch (wParam) { case OS.SIZE_RESTORED: case OS.SIZE_MAXIMIZED: - newWidth = lParam & 0xFFFF; - newHeight = lParam >> 16; + newWidth = OS.LOWORD (lParam); + newHeight = OS.HIWORD (lParam); break; case OS.SIZE_MINIMIZED: Rectangle rect = getClientArea (); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Dialog.d --- a/dwt/widgets/Dialog.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Dialog.d Sat May 17 17:34:28 2008 +0200 @@ -17,6 +17,7 @@ import dwt.DWTException; import dwt.widgets.Shell; import dwt.widgets.Display; +import dwt.widgets.Widget; import dwt.dwthelper.utils; /** @@ -170,6 +171,20 @@ parent.checkWidget (); } +static int checkStyle (Shell parent, int style) { + if ((style & (DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) is 0) { + style |= DWT.APPLICATION_MODAL; + } + style &= ~DWT.MIRRORED; + if ((style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT)) is 0) { + if (parent !is null) { + if ((parent.style & DWT.LEFT_TO_RIGHT) !is 0) style |= DWT.LEFT_TO_RIGHT; + if ((parent.style & DWT.RIGHT_TO_LEFT) !is 0) style |= DWT.RIGHT_TO_LEFT; + } + } + return Widget.checkBits (style, DWT.LEFT_TO_RIGHT, DWT.RIGHT_TO_LEFT, 0, 0, 0, 0); +} + /** * Does whatever dialog specific cleanup is required, and then * uses the code in DWTError.error to handle the error. diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/DirectoryDialog.d --- a/dwt/widgets/DirectoryDialog.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/DirectoryDialog.d Sat May 17 17:34:28 2008 +0200 @@ -58,7 +58,7 @@ *
    */ public this (Shell parent) { - this (parent, DWT.PRIMARY_MODAL); + this (parent, DWT.APPLICATION_MODAL); } /** @@ -86,7 +86,7 @@ * */ public this (Shell parent, int style) { - super (parent, style); + super (parent, checkStyle (parent, style)); checkSubclass (); } @@ -193,11 +193,11 @@ if (lpfn is null) DWT.error (DWT.ERROR_NO_MORE_CALLBACKS); /* Make the parent shell be temporary modal */ - Shell oldModal = null; + Dialog oldModal = null; Display display = parent.getDisplay (); if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { - oldModal = display.getModalDialogShell (); - display.setModalDialogShell (parent); + oldModal = display.getModalDialog (); + display.setModalDialog (this); } directoryPath = null; @@ -245,7 +245,7 @@ /* Clear the temporary dialog modal parent */ if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { - display.setModalDialogShell (oldModal); + display.setModalDialog (oldModal); } bool success = lpItemIdList !is null; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Display.d --- a/dwt/widgets/Display.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Display.d Sat May 17 17:34:28 2008 +0200 @@ -30,9 +30,11 @@ import dwt.graphics.Rectangle; import dwt.graphics.Resource; import dwt.internal.ImageList; +import dwt.internal.Library; import dwt.internal.win32.OS; import dwt.widgets.Control; +import dwt.widgets.Dialog; import dwt.widgets.Tray; import dwt.widgets.Event; import dwt.widgets.EventTable; @@ -143,7 +145,7 @@ * platforms and should never be accessed from application code. *

    */ - public MSG msg; + public MSG* msg; /* Windows and Events */ Event [] eventQueue; @@ -157,9 +159,9 @@ EventTable eventTable, filterTable; /* Widget Table */ + int freeSlot; int [] indexTable; Control lastControl, lastGetControl; - int freeSlot; HANDLE lastHwnd; HWND lastGetHwnd; Control [] controlTable; @@ -228,8 +230,8 @@ //Callback msgFilterCallback; //int msgFilterProc_, HHOOK filterHook; - MSG hookMsg; - bool runDragDrop = true; + bool runDragDrop = true, dragCancelled = false; + MSG* hookMsg; /* Idle Hook */ //Callback foregroundIdleCallback; @@ -248,8 +250,9 @@ /* Sync/Async Widget Communication */ Synchronizer synchronizer; - bool runMessages = true, runMessagesInIdle = false; + bool runMessages = true, runMessagesInIdle = false, runMessagesInMessageProc = true; static const String RUN_MESSAGES_IN_IDLE_KEY = "org.eclipse.swt.internal.win32.runMessagesInIdle"; //$NON-NLS-1$ + static final String RUN_MESSAGES_IN_MESSAGE_PROC_KEY = "dwt.internal.win32.runMessagesInMessageProc"; //$NON-NLS-1$ Thread thread; /* Display Shutdown */ @@ -260,16 +263,17 @@ int nextTrayId; /* Timers */ - int [] timerIds; + int /*long*/ [] timerIds; Runnable [] timerList; - int nextTimerId = SETTINGS_ID + 1; + int /*long*/ nextTimerId = SETTINGS_ID + 1; static const int SETTINGS_ID = 100; static const int SETTINGS_DELAY = 2000; /* Keyboard and Mouse */ - RECT clickRect; + RECT* clickRect; int clickCount, lastTime, lastButton; HWND lastClickHwnd; + int scrollRemainder; int lastKey, lastAscii, lastMouse; bool lastVirtual, lastNull, lastDead; ubyte [256] keyboard; @@ -308,6 +312,15 @@ /* Table */ char [] tableBuffer; + NMHDR* hdr; + NMLVDISPINFO* plvfi; + HWND hwndParent; + int columnCount; + bool [] columnVisible; + + /* Resize and move recursion */ + int resizeCount; + static final int RESIZE_LIMIT = 4; /* Display Data */ Object data; @@ -404,7 +417,7 @@ /* Modality */ Shell [] modalShells; - Shell modalDialogShell; + Dialog modalDialog; static bool TrimEnabled = false; /* Private DWT Window Messages */ @@ -417,6 +430,7 @@ static const int SWT_RUNASYNC = OS.WM_APP + 6; static int SWT_TASKBARCREATED; static int SWT_RESTORECARET; + static int DI_GETDRAGIMAGE; /* Workaround for Adobe Reader 7.0 */ int hitCount; @@ -490,6 +504,8 @@ */ public this (DeviceData data) { static_this(); + msg = new MSG(); + hookMsg = new MSG(); super (data); synchronizer = new Synchronizer (this); cursors = new Cursor [DWT.CURSOR_HAND + 1]; @@ -534,7 +550,7 @@ static if (USE_PROPERTY) { OS.SetProp (handle, cast(wchar*)SWT_OBJECT_INDEX, cast(void*) freeSlot + 1); } else { - OS.SetWindowLong (handle, OS.GWL_USERDATA, freeSlot + 1); + OS.SetWindowLongPtr (handle, OS.GWLP_USERDATA, freeSlot + 1); } int oldSlot = freeSlot; freeSlot = indexTable [oldSlot]; @@ -692,8 +708,10 @@ * @see #syncExec */ public void asyncExec (Runnable runnable) { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - synchronizer.asyncExec (runnable); + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + synchronizer.asyncExec (runnable); + } } /** @@ -732,11 +750,13 @@ if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); } -static synchronized void checkDisplay (Thread thread, bool multiple) { - for (int i=0; i= 0) { - if (getMessageCount () !is 0) { - if (runMessagesInIdle) { + if (code >= 0) { + if (runMessages && getMessageCount () !is 0) { + if (runMessagesInIdle) { + if (runMessagesInMessageProc) { OS.PostMessage (hwndMessage, SWT_RUNASYNC, 0, 0); + } else { + runAsyncMessages (false); } - wakeThread (); } + wakeThread (); } } return OS.CallNextHookEx (idleHook, code, wParam, lParam); @@ -1352,15 +1377,17 @@ * @param thread the user-interface thread * @return the display for the given thread */ -public static synchronized Display findDisplay (Thread thread) { +public static Display findDisplay (Thread thread) { static_this(); - for (int i=0; i> 16); - if (lastClickHwnd is hwnd && lastButton is button && (deltaTime <= doubleClick) && OS.PtInRect (&clickRect, pt)) { + OS.POINTSTOPOINT (pt, lParam); + if (lastClickHwnd is hwnd && lastButton is button && (deltaTime <= doubleClick) && OS.PtInRect (clickRect, pt)) { clickCount++; } else { clickCount = 1; @@ -1438,8 +1465,8 @@ lastTime = getLastEventTime (); int xInset = OS.GetSystemMetrics (OS.SM_CXDOUBLECLK) / 2; int yInset = OS.GetSystemMetrics (OS.SM_CYDOUBLECLK) / 2; - int x = cast(short) (lParam & 0xFFFF), y = cast(short) (lParam >> 16); - OS.SetRect (&clickRect, x - xInset, y - yInset, x + xInset, y + yInset); + int x = OS.GET_X_LPARAM (lParam), y = OS.GET_Y_LPARAM (lParam); + OS.SetRect (clickRect, x - xInset, y - yInset, x + xInset, y + yInset); //FALL THROUGH case DWT.MouseUp: return clickCount; @@ -1489,7 +1516,7 @@ static if (USE_PROPERTY) { index = cast(int) OS.GetProp (handle, cast(wchar*)SWT_OBJECT_INDEX) - 1; } else { - index = OS.GetWindowLong (handle, OS.GWL_USERDATA) - 1; + index = OS.GetWindowLongPtr (handle, OS.GWLP_USERDATA) - 1; } if (0 <= index && index < controlTable.length) { Control control = controlTable [index]; @@ -1572,10 +1599,12 @@ * * @return the default display */ -public static synchronized Display getDefault () { +public static Display getDefault () { static_this(); - if (Default is null) Default = new Display (); - return Default; + synchronized (Device.classinfo) { + if (Default is null) Default = new Display (); + return Default; + } } //PORTING_TODO @@ -1616,6 +1645,9 @@ if (key ==/*eq*/RUN_MESSAGES_IN_IDLE_KEY) { return new ValueWrapperBool(runMessagesInIdle); } + if (key.equals (RUN_MESSAGES_IN_MESSAGE_PROC_KEY)) { + return new Boolean (runMessagesInMessageProc); + } if (keys.length is 0) return null; for (int i=0; i= 0 && wParam !is OS.PM_NOREMOVE) { + if (code >= 0 && (wParam & OS.PM_REMOVE) !is 0) { MSG* msg = cast(MSG*)lParam; switch (msg.message) { case OS.WM_KEYDOWN: @@ -2167,6 +2198,23 @@ } /** + * Gets the synchronizer used by the display. + * + * @return the receiver's synchronizer + * + * @exception DWTException
      + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
    • + *
    + * + * @since 3.4 + */ +public Synchronizer getSynchronizer () { + checkDevice (); + return synchronizer; +} + +/** * Returns the thread that has invoked syncExec * or null if no such runnable is currently being invoked by * the user-interface thread. @@ -2182,8 +2230,10 @@ * */ public Thread getSyncThread () { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - return synchronizer.syncThread; + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + return synchronizer.syncThread; + } } /** @@ -2414,8 +2464,10 @@ * */ public Thread getThread () { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - return thread; + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + return thread; + } } HTHEME hButtonTheme () { @@ -2475,7 +2527,7 @@ data.style |= DWT.LEFT_TO_RIGHT; } data.device = this; - data.hFont = getSystemFont ().handle; + data.font = getSystemFont (); } return hDC; } @@ -2513,6 +2565,29 @@ lpWndClass.lpfnWndProc = &windowProcFunc; lpWndClass.style = OS.CS_BYTEALIGNWINDOW | OS.CS_DBLCLKS; lpWndClass.hCursor = OS.LoadCursor (null, cast(wchar*)OS.IDC_ARROW); + + + //DWT_TODO: Check if this can be disabled for DWT + /+ + /* + * Set the default icon for the window class to IDI_APPLICATION. + * This is not necessary for native Windows applications but + * versions of Java starting at JDK 1.6 set the icon in the + * executable instead of leaving the default. + */ + if (!OS.IsWinCE && Library.JAVA_VERSION >= Library.JAVA_VERSION (1, 6, 0)) { + TCHAR[] lpszFile = NewTCHARs (0, OS.MAX_PATH); + while (OS.GetModuleFileName (0, lpszFile.ptr, lpszFile.length) is lpszFile.length) { + lpszFile = NewTCHARs (0, lpszFile.length + OS.MAX_PATH); + } + if (OS.ExtractIconEx (lpszFile.ptr, -1, null, null, 1) !is 0) { + String fileName = TCHARzToStr( lpszFile.ptr ); + if (fileName.endsWith ("java.exe") || fileName.endsWith ("javaw.exe")) { //$NON-NLS-1$ //$NON-NLS-2$ + lpWndClass.hIcon = OS.LoadIcon (0, OS.IDI_APPLICATION); + } + } + } + +/ int byteCount = windowClass_.length * TCHAR.sizeof; lpWndClass.lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory (lpWndClass.lpszClassName, windowClass_.ptr, byteCount); @@ -2520,7 +2595,9 @@ OS.HeapFree (hHeap, 0, lpWndClass.lpszClassName); /* Register the DWT drop shadow window class */ - if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) lpWndClass.style |= OS.CS_DROPSHADOW; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { + lpWndClass.style |= OS.CS_DROPSHADOW; + } byteCount = windowShadowClass.length * TCHAR.sizeof; lpWndClass.lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory (lpWndClass.lpszClassName, windowShadowClass.ptr, byteCount); @@ -2540,7 +2617,7 @@ //messageCallback = new Callback (this, "messageProc", 4); //$NON-NLS-1$ //messageProc_ = messageCallback.getAddress (); //if (messageProc_ is 0) error (DWT.ERROR_NO_MORE_CALLBACKS); - OS.SetWindowLong (hwndMessage, OS.GWL_WNDPROC, cast(int) &messageProcFunc); + OS.SetWindowLongPtr (hwndMessage, OS.GWLP_WNDPROC, cast(LONG_PTR) &messageProcFunc); /* Create the filter hook */ static if (!OS.IsWinCE) { @@ -2561,6 +2638,7 @@ /* Register custom messages message */ SWT_TASKBARCREATED = OS.RegisterWindowMessage (StrToTCHARz ( "TaskbarCreated" )); SWT_RESTORECARET = OS.RegisterWindowMessage (StrToTCHARz ( "SWT_RESTORECARET")); + DI_GETDRAGIMAGE = OS.RegisterWindowMessage (StrToTCHARz ( "ShellGetDragImage")); //$NON-NLS-1$ /* Initialize OLE */ static if (!OS.IsWinCE) OS.OleInitialize (null); @@ -2988,9 +3066,10 @@ */ if (wParam !is 0) { if (!isXMouseActive ()) { - if (modalDialogShell !is null && modalDialogShell.isDisposed ()) modalDialogShell = null; - Shell modal = modalDialogShell !is null ? modalDialogShell : getModalShell (); - if (modal !is null) { + auto hwndActive = OS.GetActiveWindow (); + if (hwndActive !is null && OS.IsWindowEnabled (hwndActive)) break; + Shell modal = modalDialog !is null ? modalDialog.parent : getModalShell (); + if (modal !is null && !modal.isDisposed ()) { auto hwndModal = modal.handle; if (OS.IsWindowEnabled (hwndModal)) { modal.bringToTop (); @@ -3017,7 +3096,8 @@ * to run. In order to avoid running code after the display * has been disposed, exit from Java. */ - System.exit (0); + /* This code is intentionally commented */ +// System.exit (0); } break; } @@ -3027,7 +3107,15 @@ if (!event.doit) return 0; break; } + case OS.WM_DWMCOLORIZATIONCOLORCHANGED: { + OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null); + break; + } case OS.WM_SETTINGCHANGE: { + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + OS.SetTimer (hwndMessage, SETTINGS_ID, SETTINGS_DELAY, null); + break; + } switch (wParam) { case 0: case 1: @@ -3107,9 +3195,10 @@ int msgFilterProc (int code, int wParam, int lParam) { switch (code) { case OS.MSGF_COMMCTRL_BEGINDRAG: { - if (!runDragDrop) { - hookMsg = *cast(MSG*)lParam; + if (!runDragDrop && !dragCancelled) { + *hookMsg = *cast(MSG*)lParam; if (hookMsg.message is OS.WM_MOUSEMOVE) { + dragCancelled = true; OS.SendMessage (hookMsg.hwnd, OS.WM_CANCELMODE, 0, 0); } } @@ -3131,7 +3220,7 @@ case OS.MSGF_SCROLLBAR: case OS.MSGF_SIZE: { if (runMessages) { - hookMsg = *cast(MSG*)lParam; + *hookMsg = *cast(MSG*)lParam; if (hookMsg.message is OS.WM_NULL) { MSG msg; int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE; @@ -3224,118 +3313,120 @@ * */ public bool post (Event event) { - if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); - if (event is null) error (DWT.ERROR_NULL_ARGUMENT); - int type = event.type; - switch (type){ - case DWT.KeyDown: - case DWT.KeyUp: { + synchronized (Device.classinfo) { + if (isDisposed ()) error (DWT.ERROR_DEVICE_DISPOSED); + if (event is null) error (DWT.ERROR_NULL_ARGUMENT); + int type = event.type; + switch (type){ + case DWT.KeyDown: + case DWT.KeyUp: { KEYBDINPUT inputs; inputs.wVk = cast(short) untranslateKey (event.keyCode); - if (inputs.wVk is 0) { - char key = event.character; - switch (key) { - case DWT.BS: inputs.wVk = cast(short) OS.VK_BACK; break; - case DWT.CR: inputs.wVk = cast(short) OS.VK_RETURN; break; - case DWT.DEL: inputs.wVk = cast(short) OS.VK_DELETE; break; - case DWT.ESC: inputs.wVk = cast(short) OS.VK_ESCAPE; break; - case DWT.TAB: inputs.wVk = cast(short) OS.VK_TAB; break; - /* - * Since there is no LF key on the keyboard, do not attempt - * to map LF to CR or attempt to post an LF key. - */ -// case DWT.LF: inputs.wVk = cast(short) OS.VK_RETURN; break; - case DWT.LF: return false; - default: { - static if (OS.IsWinCE) { - inputs.wVk = cast(int)OS.CharUpper (cast(wchar*) key); - } else { - inputs.wVk = OS.VkKeyScan (cast(short) wcsToMbcs (key, 0)); - if (inputs.wVk is -1) return false; - inputs.wVk &= 0xFF; + if (inputs.wVk is 0) { + char key = event.character; + switch (key) { + case DWT.BS: inputs.wVk = cast(short) OS.VK_BACK; break; + case DWT.CR: inputs.wVk = cast(short) OS.VK_RETURN; break; + case DWT.DEL: inputs.wVk = cast(short) OS.VK_DELETE; break; + case DWT.ESC: inputs.wVk = cast(short) OS.VK_ESCAPE; break; + case DWT.TAB: inputs.wVk = cast(short) OS.VK_TAB; break; + /* + * Since there is no LF key on the keyboard, do not attempt + * to map LF to CR or attempt to post an LF key. + */ +// case DWT.LF: inputs.wVk = cast(short) OS.VK_RETURN; break; + case DWT.LF: return false; + default: { + static if (OS.IsWinCE) { + inputs.wVk = cast(int)OS.CharUpper (cast(wchar*) key); + } else { + inputs.wVk = OS.VkKeyScan (cast(short) wcsToMbcs (key, 0)); + if (inputs.wVk is -1) return false; + inputs.wVk &= 0xFF; + } } } } - } - inputs.dwFlags = type is DWT.KeyUp ? OS.KEYEVENTF_KEYUP : 0; + inputs.dwFlags = type is DWT.KeyUp ? OS.KEYEVENTF_KEYUP : 0; auto hHeap = OS.GetProcessHeap (); auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof); pInputs.type = OS.INPUT_KEYBOARD; - pInputs.ki = inputs; - //OS.MoveMemory (pInputs + 4, inputs, KEYBDINPUT.sizeof); - bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0; - OS.HeapFree (hHeap, 0, pInputs); - return result; - } - case DWT.MouseDown: - case DWT.MouseMove: - case DWT.MouseUp: - case DWT.MouseWheel: { - MOUSEINPUT inputs; - if (type is DWT.MouseMove){ - inputs.dwFlags = OS.MOUSEEVENTF_MOVE | OS.MOUSEEVENTF_ABSOLUTE; - int x= 0, y = 0, width = 0, height = 0; - if (OS.WIN32_VERSION >= OS.VERSION (5, 0)) { - inputs.dwFlags |= OS.MOUSEEVENTF_VIRTUALDESK; - x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN); - y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN); - width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN); - height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN); + //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit + pInputs.ki = inputs; + //OS.MoveMemory (pInputs + 4, inputs, KEYBDINPUT.sizeof); + bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0; + OS.HeapFree (hHeap, 0, pInputs); + return result; + } + case DWT.MouseDown: + case DWT.MouseMove: + case DWT.MouseUp: + case DWT.MouseWheel: { + MOUSEINPUT inputs; + if (type is DWT.MouseMove){ + inputs.dwFlags = OS.MOUSEEVENTF_MOVE | OS.MOUSEEVENTF_ABSOLUTE; + int x= 0, y = 0, width = 0, height = 0; + if (OS.WIN32_VERSION >= OS.VERSION (5, 0)) { + inputs.dwFlags |= OS.MOUSEEVENTF_VIRTUALDESK; + x = OS.GetSystemMetrics (OS.SM_XVIRTUALSCREEN); + y = OS.GetSystemMetrics (OS.SM_YVIRTUALSCREEN); + width = OS.GetSystemMetrics (OS.SM_CXVIRTUALSCREEN); + height = OS.GetSystemMetrics (OS.SM_CYVIRTUALSCREEN); + } else { + width = OS.GetSystemMetrics (OS.SM_CXSCREEN); + height = OS.GetSystemMetrics (OS.SM_CYSCREEN); + } + inputs.dx = ((event.x - x) * 65535 + width - 2) / (width - 1); + inputs.dy = ((event.y - y) * 65535 + height - 2) / (height - 1); } else { - width = OS.GetSystemMetrics (OS.SM_CXSCREEN); - height = OS.GetSystemMetrics (OS.SM_CYSCREEN); - } - inputs.dx = ((event.x - x) * 65535 + width - 2) / (width - 1); - inputs.dy = ((event.y - y) * 65535 + height - 2) / (height - 1); - } else { - if (type is DWT.MouseWheel) { - if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false; - inputs.dwFlags = OS.MOUSEEVENTF_WHEEL; - switch (event.detail) { - case DWT.SCROLL_PAGE: - inputs.mouseData = event.count * OS.WHEEL_DELTA; - break; - case DWT.SCROLL_LINE: - int value; - OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0); - inputs.mouseData = event.count * OS.WHEEL_DELTA / value; - break; - default: return false; - } - } else { - switch (event.button) { - case 1: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break; - case 2: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break; - case 3: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break; - case 4: { - if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false; - inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP; - inputs.mouseData = OS.XBUTTON1; - break; + if (type is DWT.MouseWheel) { + if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false; + inputs.dwFlags = OS.MOUSEEVENTF_WHEEL; + switch (event.detail) { + case DWT.SCROLL_PAGE: + inputs.mouseData = event.count * OS.WHEEL_DELTA; + break; + case DWT.SCROLL_LINE: + int value; + OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0); + inputs.mouseData = event.count * OS.WHEEL_DELTA / value; + break; + default: return false; } - case 5: { - if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false; - inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP; - inputs.mouseData = OS.XBUTTON2; - break; + } else { + switch (event.button) { + case 1: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_LEFTDOWN : OS.MOUSEEVENTF_LEFTUP; break; + case 2: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_MIDDLEDOWN : OS.MOUSEEVENTF_MIDDLEUP; break; + case 3: inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_RIGHTDOWN : OS.MOUSEEVENTF_RIGHTUP; break; + case 4: { + if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false; + inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP; + inputs.mouseData = OS.XBUTTON1; + break; + } + case 5: { + if (OS.WIN32_VERSION < OS.VERSION (5, 0)) return false; + inputs.dwFlags = type is DWT.MouseDown ? OS.MOUSEEVENTF_XDOWN : OS.MOUSEEVENTF_XUP; + inputs.mouseData = OS.XBUTTON2; + break; + } + default: return false; } - default: return false; } } + auto hHeap = OS.GetProcessHeap (); + auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof); + pInputs.type = OS.INPUT_MOUSE; + //TODO - DWORD type of INPUT structure aligned to 8 bytes on 64 bit + pInputs.mi = inputs; + bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0; + OS.HeapFree (hHeap, 0, pInputs); + return result; } - auto hHeap = OS.GetProcessHeap (); - auto pInputs = cast(INPUT*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, INPUT.sizeof); - pInputs.type = OS.INPUT_MOUSE; - //OS.MoveMemory(pInputs, [OS.INPUT_MOUSE], 4); - pInputs.mi = inputs; - //OS.MoveMemory (pInputs + 4, inputs, MOUSEINPUT.sizeof); - bool result = OS.SendInput (1, pInputs, INPUT.sizeof) !is 0; - OS.HeapFree (hHeap, 0, pInputs); - return result; + default: } - default: + return false; } - return false; } void postEvent (Event event) { @@ -3389,10 +3480,10 @@ lpStartupInfo = null; drawMenuBars (); runPopups (); - if (OS.PeekMessage (&msg, null, 0, 0, OS.PM_REMOVE)) { - if (!filterMessage (&msg)) { - OS.TranslateMessage (&msg); - OS.DispatchMessage (&msg); + if (OS.PeekMessage (msg, null, 0, 0, OS.PM_REMOVE)) { + if (!filterMessage (msg)) { + OS.TranslateMessage (msg); + OS.DispatchMessage (msg); } runDeferredEvents (); return true; @@ -3400,18 +3491,20 @@ return runMessages && runAsyncMessages (false); } -static synchronized void register (Display display) { +static void register (Display display) { static_this(); - for (int i=0; i= 0) { if (types [index] !is 0) break; @@ -43,10 +61,10 @@ } index++; if (index is length) { - int [] newTypes = new int [length + 4]; + int [] newTypes = new int [length + GROW_SIZE]; System.arraycopy (types, 0, newTypes, 0, length); types = newTypes; - Listener [] newListeners = new Listener [length + 4]; + Listener [] newListeners = new Listener [length + GROW_SIZE]; SimpleType!(Listener).arraycopy (listeners, 0, newListeners, 0, length); listeners = newListeners; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/ExpandBar.d --- a/dwt/widgets/ExpandBar.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/ExpandBar.d Sat May 17 17:34:28 2008 +0200 @@ -285,27 +285,34 @@ int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); drawFocus = (uiState & OS.UISF_HIDEFOCUS) is 0; } - HFONT hCaptionFont, oldFont; + HFONT hCurrentFont, oldFont; if (hTheme is null) { - static if (!OS.IsWinCE ) { - if (hFont is null) { + if (hFont !is null) { + hCurrentFont = hFont; + } else { + if (!OS.IsWinCE) { NONCLIENTMETRICS info; info.cbSize = NONCLIENTMETRICS.sizeof; if (OS.SystemParametersInfo (OS.SPI_GETNONCLIENTMETRICS, 0, &info, 0)) { LOGFONT* logFont = &info.lfCaptionFont; - hCaptionFont = OS.CreateFontIndirect (logFont); - oldFont = OS.SelectObject (gc.handle, hCaptionFont); + hCurrentFont = OS.CreateFontIndirect (logFont); } } } + if (hCurrentFont !is null) { + oldFont = OS.SelectObject (gc.handle, hCurrentFont); + } + if (foreground !is -1) { + OS.SetTextColor (gc.handle, foreground); + } } for (int i = 0; i < itemCount; i++) { ExpandItem item = items[i]; item.drawItem (gc, hTheme, clipRect, item is focusItem && drawFocus); } - if (hCaptionFont !is null) { + if (hCurrentFont !is null) { OS.SelectObject (gc.handle, oldFont); - OS.DeleteObject (hCaptionFont); + if (hCurrentFont !is hFont) OS.DeleteObject (hCurrentFont); } } @@ -582,8 +589,44 @@ layoutItems (index + 1, true); } +void showFocus (bool up) { + RECT rect; + OS.GetClientRect (handle, &rect); + int height = rect.bottom - rect.top; + int updateY = 0; + if (up) { + if (focusItem.y < 0) { + updateY = Math.min (yCurrentScroll, -focusItem.y); + } + } else { + int itemHeight = focusItem.y + getBandHeight (); + if (focusItem.expanded) { + if (height >= getBandHeight () + focusItem.height) { + itemHeight += focusItem.height; + } + } + if (itemHeight > height) { + updateY = height - itemHeight; + } + } + if (updateY !is 0) { + yCurrentScroll = Math.max (0, yCurrentScroll - updateY); + if ((style & DWT.V_SCROLL) !is 0) { + SCROLLINFO info; + info.cbSize = SCROLLINFO.sizeof; + info.fMask = OS.SIF_POS; + info.nPos = yCurrentScroll; + OS.SetScrollInfo (handle, OS.SB_VERT, &info, true); + } + OS.ScrollWindowEx (handle, 0, updateY, null, null, null, null, OS.SW_SCROLLCHILDREN | OS.SW_INVALIDATE); + for (int i = 0; i < itemCount; i++) { + items [i].y += updateY; + } + } +} + override String windowClass () { - return display.windowClass(); + return display.windowClass; } override int windowProc () { @@ -610,6 +653,7 @@ focusItem.redraw (true); focusItem = items [focusIndex - 1]; focusItem.redraw (true); + showFocus (true); return LRESULT.ZERO; } break; @@ -620,6 +664,7 @@ focusItem.redraw (true); focusItem = items [focusIndex + 1]; focusItem.redraw (true); + showFocus (false); return LRESULT.ZERO; } break; @@ -630,18 +675,16 @@ } override LRESULT WM_KILLFOCUS (int wParam, int lParam) { -trc(__LINE__); LRESULT result = super.WM_KILLFOCUS (wParam, lParam); if (focusItem !is null) focusItem.redraw (true); return result; } override LRESULT WM_LBUTTONDOWN (int wParam, int lParam) { -//trc(__LINE__); LRESULT result = super.WM_LBUTTONDOWN (wParam, lParam); if (result is LRESULT.ZERO) return result; - int x = cast(short) (lParam & 0xFFFF); - int y = cast(short) (lParam >> 16); + int x = OS.GET_X_LPARAM (lParam); + int y = OS.GET_Y_LPARAM (lParam); for (int i = 0; i < itemCount; i++) { ExpandItem item = items[i]; bool hover = item.isHover (x, y); @@ -660,8 +703,8 @@ LRESULT result = super.WM_LBUTTONUP (wParam, lParam); if (result is LRESULT.ZERO) return result; if (focusItem is null) return result; - int x = cast(short) (lParam & 0xFFFF); - int y = cast(short) (lParam >> 16); + int x = OS.GET_X_LPARAM (lParam); + int y = OS.GET_Y_LPARAM (lParam); bool hover = focusItem.isHover (x, y); if (hover) { Event event = new Event (); @@ -689,11 +732,10 @@ } override LRESULT WM_MOUSEMOVE (int wParam, int lParam) { -trc(__LINE__); LRESULT result = super.WM_MOUSEMOVE (wParam, lParam); if (result is LRESULT.ZERO) return result; - int x = cast(short) (lParam & 0xFFFF); - int y = cast(short) (lParam >> 16); + int x = OS.GET_X_LPARAM (lParam); + int y = OS.GET_Y_LPARAM (lParam); for (int i = 0; i < itemCount; i++) { ExpandItem item = items [i]; bool hover = item.isHover (x, y); @@ -753,7 +795,7 @@ trc(__LINE__); LRESULT result = super.WM_SETCURSOR (wParam, lParam); if (result !is null) return result; - int hitTest = lParam & 0xFFFF; + int hitTest = cast(short) OS.LOWORD (lParam); if (hitTest is OS.HTCLIENT) { for (int i = 0; i < itemCount; i++) { ExpandItem item = items [i]; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/FileDialog.d --- a/dwt/widgets/FileDialog.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/FileDialog.d Sat May 17 17:34:28 2008 +0200 @@ -43,9 +43,24 @@ String [] filterExtensions; String [] fileNames; String filterPath = "", fileName = ""; - static final String FILTER = "*.*"; + int filterIndex = 0; + bool overwrite = false; + static const String FILTER = "*.*"; static int BUFFER_SIZE = 1024 * 32; - static bool USE_HOOK; + static bool USE_HOOK = true; + static this() { + /* + * Feature in Vista. When OFN_ENABLEHOOK is set in the + * save or open file dialog, Vista uses the old XP look + * and feel. OFN_ENABLEHOOK is used to grow the file + * name buffer in a multi-select file dialog. The fix + * is to only use OFN_ENABLEHOOK when the buffer has + * overrun. + */ + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + USE_HOOK = false; + } + } /** * Constructs a new instance of this class given only its parent. @@ -61,7 +76,7 @@ * */ public this (Shell parent) { - this (parent, DWT.PRIMARY_MODAL); + this (parent, DWT.APPLICATION_MODAL); } /** @@ -89,7 +104,7 @@ * */ public this (Shell parent, int style) { - super (parent, style); + super (parent, checkStyle (parent, style)); checkSubclass (); } @@ -125,6 +140,26 @@ } /** + * Get the 0-based index of the file extension filter + * which was selected by the user, or -1 if no filter + * was selected. + *

    + * This is an index into the FilterExtensions array and + * the FilterNames array. + *

    + * + * @return index the file extension filter index + * + * @see #getFilterExtensions + * @see #getFilterNames + * + * @since 3.4 + */ +public int getFilterIndex () { + return filterIndex; +} + +/** * Returns the names that describe the filter extensions * which the dialog will use to filter the files it shows. * @@ -147,6 +182,19 @@ return filterPath; } +/** + * Returns the flag that the dialog will use to + * determine whether to prompt the user for file + * overwrite if the selected file already exists. + * + * @return true if the dialog will prompt for file overwrite, false otherwise + * + * @since 3.4 + */ +public bool getOverwrite () { + return overwrite; +} + private static extern(Windows) uint OFNHookProc (HWND hdlg, uint uiMsg, uint wParam, int lParam) { switch (uiMsg) { case OS.WM_NOTIFY: @@ -193,7 +241,35 @@ /* Get the owner HWND for the dialog */ HWND hwndOwner; - if (parent !is null) hwndOwner = parent.handle; + auto hwndParent = parent.handle; + + /* + * Feature in Windows. There is no API to set the orientation of a + * file dialog. It is always inherited from the parent. The fix is + * to create a hidden parent and set the orientation in the hidden + * parent for the dialog to inherit. + */ + bool enabled = false; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) { + int dialogOrientation = style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT); + int parentOrientation = parent.style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT); + if (dialogOrientation !is parentOrientation) { + int exStyle = OS.WS_EX_NOINHERITLAYOUT; + if (dialogOrientation is DWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL; + hwndOwner = OS.CreateWindowEx ( + exStyle, + Shell.DialogClass.ptr, + null, + 0, + OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, + hwndParent, + null, + OS.GetModuleHandle (null), + null); + enabled = OS.IsWindowEnabled (hwndParent) !is 0; + if (enabled) OS.EnableWindow (hwndParent, false); + } + } /* Convert the title and copy it into lpstrTitle */ if (title is null) title = ""; @@ -253,7 +329,8 @@ OPENFILENAME struct_; struct_.lStructSize = OPENFILENAME.sizeof; struct_.Flags = OS.OFN_HIDEREADONLY | OS.OFN_NOCHANGEDIR; - //Callback callback = null; + bool save = (style & DWT.SAVE) !is 0; + if (save && overwrite) struct_.Flags |= OS.OFN_OVERWRITEPROMPT; if ((style & DWT.MULTI) !is 0) { struct_.Flags |= OS.OFN_ALLOWMULTISELECT | OS.OFN_EXPLORER; if (!OS.IsWinCE && USE_HOOK) { @@ -271,7 +348,7 @@ struct_.nMaxFile = nMaxFile; struct_.lpstrInitialDir = lpstrInitialDir; struct_.lpstrFilter = lpstrFilter; - struct_.nFilterIndex = 0; + struct_.nFilterIndex = filterIndex is 0 ? filterIndex : filterIndex + 1; /* * Set the default extension to an empty string. If the @@ -280,18 +357,17 @@ * extension at the time that the dialog is closed. */ TCHAR* lpstrDefExt; - bool save = (style & DWT.SAVE) !is 0; if (save) { lpstrDefExt = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, TCHAR.sizeof); struct_.lpstrDefExt = lpstrDefExt; } /* Make the parent shell be temporary modal */ - Shell oldModal = null; + Dialog oldModal = null; Display display = parent.getDisplay (); if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { - oldModal = display.getModalDialogShell (); - display.setModalDialogShell (parent); + oldModal = display.getModalDialog (); + display.setModalDialog (this); } /* @@ -327,7 +403,7 @@ /* Clear the temporary dialog modal parent */ if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { - display.setModalDialogShell (oldModal); + display.setModalDialog (oldModal); } /* Dispose the callback and reassign the buffer */ @@ -335,7 +411,7 @@ lpstrFile = struct_.lpstrFile; /* Set the new path, file name and filter */ - fileNames = new String [0]; + fileNames = null; String fullPath = null; if (success) { @@ -408,6 +484,7 @@ fileNames = newFileNames; } } + filterIndex = struct_.nFilterIndex - 1; } /* Free the memory that was allocated. */ @@ -417,6 +494,13 @@ OS.HeapFree (hHeap, 0, lpstrTitle); if (lpstrDefExt !is null) OS.HeapFree (hHeap, 0, lpstrDefExt); + /* Destroy the BIDI orientation window */ + if (hwndParent !is hwndOwner) { + if (enabled) OS.EnableWindow (hwndParent, true); + OS.SetActiveWindow (hwndParent); + OS.DestroyWindow (hwndOwner); + } + /* * This code is intentionally commented. On some * platforms, the owner window is repainted right @@ -461,7 +545,27 @@ } /** - * Sets the the names that describe the filter extensions + * Set the 0-based index of the file extension filter + * which the dialog will use initially to filter the files + * it shows to the argument. + *

    + * This is an index into the FilterExtensions array and + * the FilterNames array. + *

    + * + * @param index the file extension filter index + * + * @see #setFilterExtensions + * @see #setFilterNames + * + * @since 3.4 + */ +public void setFilterIndex (int index) { + filterIndex = index; +} + +/** + * Sets the names that describe the filter extensions * which the dialog will use to filter the files it shows * to the argument, which may be null. *

    @@ -499,5 +603,17 @@ filterPath = string; } +/** + * Sets the flag that the dialog will use to + * determine whether to prompt the user for file + * overwrite if the selected file already exists. + * + * @param overwrite true if the dialog will prompt for file overwrite, false otherwise + * + * @since 3.4 + */ +public void setOverwrite (bool overwrite) { + this.overwrite = overwrite; +} } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/FontDialog.d --- a/dwt/widgets/FontDialog.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/FontDialog.d Sat May 17 17:34:28 2008 +0200 @@ -58,7 +58,7 @@ * */ public this (Shell parent) { - this (parent, DWT.PRIMARY_MODAL); + this (parent, DWT.APPLICATION_MODAL); } /** @@ -86,7 +86,7 @@ * */ public this (Shell parent, int style) { - super (parent, style); + super (parent, checkStyle (parent, style)); checkSubclass (); } @@ -145,8 +145,36 @@ static if (OS.IsWinCE) DWT.error (DWT.ERROR_NOT_IMPLEMENTED); /* Get the owner HWND for the dialog */ - HWND hwndOwner; - if (parent !is null) hwndOwner = parent.handle; + HWND hwndOwner = parent.handle; + auto hwndParent = parent.handle; + + /* + * Feature in Windows. There is no API to set the orientation of a + * font dialog. It is always inherited from the parent. The fix is + * to create a hidden parent and set the orientation in the hidden + * parent for the dialog to inherit. + */ + bool enabled = false; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) { + int dialogOrientation = style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT); + int parentOrientation = parent.style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT); + if (dialogOrientation !is parentOrientation) { + int exStyle = OS.WS_EX_NOINHERITLAYOUT; + if (dialogOrientation is DWT.RIGHT_TO_LEFT) exStyle |= OS.WS_EX_LAYOUTRTL; + hwndOwner = OS.CreateWindowEx ( + exStyle, + Shell.DialogClass.ptr, + null, + 0, + OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, + hwndParent, + null, + OS.GetModuleHandle (null), + null); + enabled = OS.IsWindowEnabled (hwndParent) !is 0; + if (enabled) OS.EnableWindow (hwndParent, false); + } + } /* Open the dialog */ auto hHeap = OS.GetProcessHeap (); @@ -175,12 +203,12 @@ } /* Make the parent shell be temporary modal */ - Shell oldModal = null; + Dialog oldModal = null; Display display = null; if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { display = parent.getDisplay (); - oldModal = display.getModalDialogShell (); - display.setModalDialogShell (parent); + oldModal = display.getModalDialog (); + display.setModalDialog (this); } /* Open the dialog */ @@ -188,7 +216,7 @@ /* Clear the temporary dialog modal parent */ if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { - display.setModalDialogShell (oldModal); + display.setModalDialog (oldModal); } /* Compute the result */ @@ -235,6 +263,13 @@ /* Free the OS memory */ if (lpLogFont !is null) OS.HeapFree (hHeap, 0, lpLogFont); + /* Destroy the BIDI orientation window */ + if (hwndParent !is hwndOwner) { + if (enabled) OS.EnableWindow (hwndParent, true); + OS.SetActiveWindow (hwndParent); + OS.DestroyWindow (hwndOwner); + } + /* * This code is intentionally commented. On some * platforms, the owner window is repainted right diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Group.d --- a/dwt/widgets/Group.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Group.d Sat May 17 17:34:28 2008 +0200 @@ -207,7 +207,8 @@ OS.DrawText (hDC, buffer, -1, &rect, flags); if (newFont !is null) OS.SelectObject (hDC, oldFont); OS.ReleaseDC (handle, hDC); - size.x = Math.max (size.x, rect.right - rect.left + CLIENT_INSET * 6); + int offsetY = OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed () ? 0 : 1; + size.x = Math.max (size.x, rect.right - rect.left + CLIENT_INSET * 6 + offsetY); } return size; } @@ -223,15 +224,27 @@ OS.GetTextMetrics (hDC, &tm); if (newFont !is null) OS.SelectObject (hDC, oldFont); OS.ReleaseDC (handle, hDC); + int offsetY = OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed () ? 0 : 1; trim.x -= CLIENT_INSET; - trim.y -= tm.tmHeight; + trim.y -= tm.tmHeight + offsetY; trim.width += CLIENT_INSET * 2; trim.height += tm.tmHeight + CLIENT_INSET; return trim; } override void createHandle () { + /* + * Feature in Windows. When a button is created, + * it clears the UI state for all controls in the + * shell by sending WM_CHANGEUISTATE with UIS_SET, + * UISF_HIDEACCEL and UISF_HIDEFOCUS to the parent. + * This is undocumented and unexpected. The fix + * is to ignore the WM_CHANGEUISTATE, when sent + * from CreateWindowEx(). + */ + parent.state |= IGNORE_WM_CHANGEUISTATE; super.createHandle (); + parent.state &= ~IGNORE_WM_CHANGEUISTATE; state |= DRAW_BACKGROUND; state &= ~CANVAS; } @@ -265,7 +278,8 @@ OS.GetTextMetrics (hDC, &tm); if (newFont !is null) OS.SelectObject (hDC, oldFont); OS.ReleaseDC (handle, hDC); - int x = CLIENT_INSET, y = tm.tmHeight; + int offsetY = OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed () ? 0 : 1; + int x = CLIENT_INSET, y = tm.tmHeight + offsetY; int width = Math.max (0, rect.right - CLIENT_INSET * 2); int height = Math.max (0, rect.bottom - y - CLIENT_INSET); return new Rectangle (x, y, width, height); @@ -406,7 +420,7 @@ * allow children, answer HTCLIENT to allow mouse messages * to be delivered to the children. */ - int code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); if (code is OS.HTTRANSPARENT) code = OS.HTCLIENT; return new LRESULT (code); } @@ -438,7 +452,7 @@ */ if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { auto nSavedDC = OS.SaveDC (cast(HDC)wParam); - int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam); OS.RestoreDC (cast(HDC)wParam, nSavedDC); return new LRESULT (code); } @@ -467,7 +481,7 @@ } if (redraw) { OS.InvalidateRect (handle, null, false); - int code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam); + int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam); return new LRESULT (code); } return result; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/IME.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/widgets/IME.d Sat May 17 17:34:28 2008 +0200 @@ -0,0 +1,429 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.widgets.IME; + + +import dwt.DWT; +import dwt.graphics.Color; +import dwt.graphics.TextStyle; +import dwt.internal.win32.OS; +import dwt.internal.win32.WINTYPES; + +import dwt.widgets.Widget; +import dwt.widgets.Canvas; +import dwt.widgets.Event; +import dwt.widgets.Display; + +import dwt.dwthelper.utils; + +/** + * TODO - JAVA DOC + * + *

    + *
    Styles:
    + *
    (none)
    + *
    Events:
    + *
    (none)
    + *
    + *

    + * . + *

    + * + * @since 3.4 + */ + +public class IME : Widget { + Canvas parent; + int caretOffset; + int startOffset; + int commitCount; + String text; + int [] ranges; + TextStyle [] styles; + + static const int WM_MSIME_MOUSE; + + static byte [16] IID_ITfInputProcessorProfiles; + static byte [16] IID_ITfDisplayAttributeProvider; + static byte [16] CLSID_TF_InputProcessorProfiles; + static byte [16] GUID_TFCAT_TIP_KEYBOARD; + static this() { + WM_MSIME_MOUSE = OS.RegisterWindowMessage (StrToTCHARz ("MSIMEMouseOperation")); + + OS.IIDFromString ("{1F02B6C5-7842-4EE6-8A0B-9A24183A95CA}\0"w.ptr, IID_ITfInputProcessorProfiles.ptr); + OS.IIDFromString ("{fee47777-163c-4769-996a-6e9c50ad8f54}\0"w.ptr, IID_ITfDisplayAttributeProvider.ptr); + OS.IIDFromString ("{33C53A50-F456-4884-B049-85FD643ECFED}\0"w.ptr, CLSID_TF_InputProcessorProfiles.ptr); + OS.IIDFromString ("{34745C63-B2F0-4784-8B67-5E12C8701A31}\0"w.ptr, GUID_TFCAT_TIP_KEYBOARD.ptr); + } + + /* TextLayout has a copy of these constants */ + static const int UNDERLINE_IME_DOT = 1 << 16; + static const int UNDERLINE_IME_DASH = 2 << 16; + static const int UNDERLINE_IME_THICK = 3 << 16; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this () { +} + +/** + * + * @see DWT + */ +public this (Canvas parent, int style) { + super (parent, style); + this.parent = parent; + createWidget (); +} + +void createWidget () { + text = ""; + startOffset = -1; + if (parent.getIME () is null) { + parent.setIME (this); + } +} + +public int getCaretOffset () { + checkWidget (); + return startOffset + caretOffset; +} + +public int getCommitCount () { + checkWidget (); + return commitCount; +} + +public int getCompositionOffset () { + checkWidget (); + return startOffset; +} + +TF_DISPLAYATTRIBUTE* getDisplayAttribute (short langid, int attInfo) { + void* pProfiles; + int hr = OS.CoCreateInstance (CLSID_TF_InputProcessorProfiles.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles.ptr, &pProfiles); + TF_DISPLAYATTRIBUTE* pda; + if (hr is OS.S_OK) { + byte [16] pclsid; + byte [16] pguidProfile; + /* pProfiles.GetDefaultLanguageProfile () */ + hr = OS.VtblCall (8, pProfiles, cast(int)langid, cast(int)GUID_TFCAT_TIP_KEYBOARD.ptr, cast(int)pclsid.ptr, cast(int)pguidProfile.ptr); + if (hr is OS.S_OK) { + void* pProvider; + hr = OS.CoCreateInstance (pclsid.ptr, null, OS.CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeProvider.ptr, &pProvider); + if (hr is OS.S_OK) { + void* pEnum; + /* pProvider.EnumDisplayAttributeInfo () */ + hr = OS.VtblCall (3, pProvider, cast(int)&pEnum); + if (hr is OS.S_OK) { + void* pDispInfo; + TF_DISPLAYATTRIBUTE* tempPda; + /* pEnum.Next () */ + while ((hr = OS.VtblCall (4, pEnum, 1, cast(int) &pDispInfo, 0 )) is OS.S_OK) { + /* pDispInfo.GetAttributeInfo(); */ + OS.VtblCall (5, pDispInfo, cast(int)&tempPda); + /* pDispInfo.Release () */ + OS.VtblCall (2, pDispInfo); + if (tempPda.bAttr is attInfo) { + pda = tempPda; + break; + } + } + /* pEnum.Release () */ + hr = OS.VtblCall (2, pEnum); + } + /* pProvider.Release () */ + hr = OS.VtblCall (2, pProvider); + } + } + /* pProfiles.Release () */ + hr = OS.VtblCall (2, pProfiles); + } + if (pda is null) { + pda = new TF_DISPLAYATTRIBUTE (); + switch (attInfo) { + case OS.TF_ATTR_INPUT: + pda.lsStyle = OS.TF_LS_SQUIGGLE; + break; + case OS.TF_ATTR_CONVERTED: + case OS.TF_ATTR_TARGET_CONVERTED: + pda.lsStyle = OS.TF_LS_SOLID; + pda.fBoldLine = attInfo is OS.TF_ATTR_TARGET_CONVERTED; + break; + } + } + return pda; +} + +public int [] getRanges () { + checkWidget (); + if (ranges is null) return new int [0]; + int [] result = new int [ranges.length]; + for (int i = 0; i < result.length; i++) { + result [i] = ranges [i] + startOffset; + } + return result; +} + +public TextStyle [] getStyles () { + checkWidget (); + if (styles is null) return new TextStyle [0]; + TextStyle [] result = new TextStyle [styles.length]; + System.arraycopy (styles, 0, result, 0, styles.length); + return result; +} + +public String getText () { + checkWidget (); + return text; +} + +public bool getWideCaret() { + checkWidget (); + auto layout = OS.GetKeyboardLayout (0); + short langID = cast(short)OS.LOWORD ( cast(int) layout); + return OS.PRIMARYLANGID (langID) is OS.LANG_KOREAN; +} + +bool isInlineEnabled () { + if (OS.IsWinCE || OS.WIN32_VERSION < OS.VERSION (5, 1)) return false; + return OS.IsDBLocale && hooks (DWT.ImeComposition); +} + +void releaseParent () { + super.releaseParent (); + if (this is parent.getIME ()) parent.setIME (null); +} + +void releaseWidget () { + super.releaseWidget (); + parent = null; + text = null; + styles = null; + ranges = null; +} + +public void setCompositionOffset (int offset) { + checkWidget (); + if (offset < 0) return; + if (startOffset !is -1) { + startOffset = offset; + } +} + +LRESULT WM_IME_COMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + if (!isInlineEnabled ()) return null; + ranges = null; + styles = null; + caretOffset = commitCount = 0; + auto hwnd = parent.handle; + auto hIMC = OS.ImmGetContext (hwnd); + int codePage = parent.getCodePage (); + if (hIMC !is null) { + TCHAR[] buffer = null; + if ((lParam & OS.GCS_RESULTSTR) !is 0) { + int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, null, 0); + if (length_ > 0) { + buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); + OS.ImmGetCompositionString (hIMC, OS.GCS_RESULTSTR, buffer.ptr, length_); + if (startOffset is -1) { + Event event = new Event (); + event.detail = DWT.COMPOSITION_SELECTION; + sendEvent (DWT.ImeComposition, event); + startOffset = event.start; + } + Event event = new Event (); + event.detail = DWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = startOffset + text.length; + event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; + commitCount = text.length ; + sendEvent (DWT.ImeComposition, event); + String chars = text; + text = ""; + startOffset = -1; + commitCount = 0; + if (event.doit) { + Display display = this.display; + display.lastKey = 0; + display.lastVirtual = display.lastNull = display.lastDead = false; + length_ = chars.length; + for (int i = 0; i < length_; i++) { + char c = chars.charAt (i); + display.lastAscii = c; + event = new Event (); + event.character = c; + parent.sendEvent (DWT.KeyDown, event); + } + } + } + if ((lParam & OS.GCS_COMPSTR) is 0) return LRESULT.ONE; + } + buffer = null; + if ((lParam & OS.GCS_COMPSTR) !is 0) { + int length_ = OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0); + if (length_ > 0) { + buffer = NewTCHARs (codePage, length_ / TCHAR.sizeof); + OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, buffer.ptr, length_); + if ((lParam & OS.GCS_CURSORPOS) !is 0) { + caretOffset = OS.ImmGetCompositionString (hIMC, OS.GCS_CURSORPOS, null, 0); + } + int [] clauses = null; + if ((lParam & OS.GCS_COMPCLAUSE) !is 0) { + length_ = OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, /+cast(int [])+/null, 0); + if (length_ > 0) { + clauses = new int [length_ / 4]; + OS.ImmGetCompositionStringW (hIMC, OS.GCS_COMPCLAUSE, clauses.ptr, length_); + } + } + if ((lParam & OS.GCS_COMPATTR) !is 0 && clauses !is null) { + length_ = OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, /+cast(byte [])+/null, 0); + if (length_ > 0) { + byte [] attrs = new byte [length_]; + OS.ImmGetCompositionStringA (hIMC, OS.GCS_COMPATTR, attrs.ptr, length_); + length_ = clauses.length - 1; + ranges = new int [length_ * 2]; + styles = new TextStyle [length_]; + auto layout = OS.GetKeyboardLayout (0); + short langID = cast(short)OS.LOWORD ( cast(int) layout); + TF_DISPLAYATTRIBUTE* attr = null; + TextStyle style = null; + for (int i = 0; i < length_; i++) { + ranges [i * 2] = clauses [i]; + ranges [i * 2 + 1] = clauses [i + 1] - 1; + styles [i] = style = new TextStyle (); + attr = getDisplayAttribute (langID, attrs [clauses [i]]); + if (attr !is null) { + switch (attr.crText.type) { + case OS.TF_CT_COLORREF: + style.foreground = Color.win32_new (display, attr.crText.cr); + break; + case OS.TF_CT_SYSCOLOR: + int colorRef = OS.GetSysColor (attr.crText.cr); + style.foreground = Color.win32_new (display, colorRef); + break; + } + switch (attr.crBk.type) { + case OS.TF_CT_COLORREF: + style.background = Color.win32_new (display, attr.crBk.cr); + break; + case OS.TF_CT_SYSCOLOR: + int colorRef = OS.GetSysColor (attr.crBk.cr); + style.background = Color.win32_new (display, colorRef); + break; + } + switch (attr.crLine.type) { + case OS.TF_CT_COLORREF: + style.underlineColor = Color.win32_new (display, attr.crLine.cr); + break; + case OS.TF_CT_SYSCOLOR: + int colorRef = OS.GetSysColor (attr.crLine.cr); + style.underlineColor = Color.win32_new (display, colorRef); + break; + } + style.underline = attr.lsStyle !is OS.TF_LS_NONE; + switch (attr.lsStyle) { + case OS.TF_LS_SQUIGGLE: + style.underlineStyle = DWT.UNDERLINE_SQUIGGLE; + break; + case OS.TF_LS_DASH: + style.underlineStyle = UNDERLINE_IME_DASH; + break; + case OS.TF_LS_DOT: + style.underlineStyle = UNDERLINE_IME_DOT; + break; + case OS.TF_LS_SOLID: + style.underlineStyle = attr.fBoldLine ? UNDERLINE_IME_THICK : DWT.UNDERLINE_SINGLE; + break; + } + } + } + } + } + } + OS.ImmReleaseContext (hwnd, hIMC); + } + int end = startOffset + text.length; + if (startOffset is -1) { + Event event = new Event (); + event.detail = DWT.COMPOSITION_SELECTION; + sendEvent (DWT.ImeComposition, event); + startOffset = event.start; + end = event.end; + } + Event event = new Event (); + event.detail = DWT.COMPOSITION_CHANGED; + event.start = startOffset; + event.end = end; + event.text = text = buffer !is null ? TCHARsToStr(buffer) : ""; + sendEvent (DWT.ImeComposition, event); + if (text.length is 0) { + startOffset = -1; + ranges = null; + styles = null; + } + } + return LRESULT.ONE; +} + +LRESULT WM_IME_COMPOSITION_START (int /*long*/ wParam, int /*long*/ lParam) { + return isInlineEnabled () ? LRESULT.ONE : null; +} + +LRESULT WM_IME_ENDCOMPOSITION (int /*long*/ wParam, int /*long*/ lParam) { + return isInlineEnabled () ? LRESULT.ONE : null; +} + +LRESULT WM_KILLFOCUS (int /*long*/ wParam, int /*long*/ lParam) { + if (!isInlineEnabled ()) return null; + auto hwnd = parent.handle; + auto hIMC = OS.ImmGetContext (hwnd); + if (hIMC !is null) { + if (OS.ImmGetOpenStatus (hIMC)) { + OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); + } + OS.ImmReleaseContext (hwnd, hIMC); + } + return null; +} + +LRESULT WM_LBUTTONDOWN (int /*long*/ wParam, int /*long*/ lParam) { + if (!isInlineEnabled ()) return null; + auto hwnd = parent.handle; + auto hIMC = OS.ImmGetContext (hwnd); + if (hIMC !is null) { + if (OS.ImmGetOpenStatus (hIMC)) { + if (OS.ImmGetCompositionString (hIMC, OS.GCS_COMPSTR, null, 0) > 0) { + Event event = new Event (); + event.detail = DWT.COMPOSITION_OFFSET; + event.x = OS.GET_X_LPARAM (lParam); + event.y = OS.GET_Y_LPARAM (lParam); + sendEvent (DWT.ImeComposition, event); + int offset = event.index; + int length_ = text.length; + if (offset !is -1 && startOffset !is -1 && startOffset <= offset && offset < startOffset + length_) { + auto imeWnd = OS.ImmGetDefaultIMEWnd (hwnd); + offset = event.index + event.count - startOffset; + int trailing = event.count > 0 ? 1 : 2; + int /*long*/ param = OS.MAKEWPARAM (OS.MAKEWORD (OS.IMEMOUSE_LDOWN, trailing), offset); + OS.SendMessage (imeWnd, WM_MSIME_MOUSE, param, hIMC); + } else { + OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); + } + } + } + OS.ImmReleaseContext (hwnd, hIMC); + } + return null; +} + +} diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Label.d --- a/dwt/widgets/Label.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Label.d Sat May 17 17:34:28 2008 +0200 @@ -34,6 +34,13 @@ * user interface object that displays a string or image. * When SEPARATOR is specified, displays a single * vertical or horizontal line. + *

    + * Shadow styles are hints and may not be honoured + * by the platform. To create a separator label + * with the default shadow style for the platform, + * do not specify a shadow style. + *

    + *
    *
    *
    Styles:
    *
    SEPARATOR, HORIZONTAL, VERTICAL
    @@ -513,6 +520,7 @@ override LRESULT WM_UPDATEUISTATE (int wParam, int lParam) { LRESULT result = super.WM_UPDATEUISTATE (wParam, lParam); + if (result !is null) return result; /* * Feature in Windows. When WM_UPDATEUISTATE is sent to * a static control, it sends WM_CTLCOLORSTATIC to get the @@ -531,7 +539,7 @@ } if (redraw) { OS.InvalidateRect (handle, null, false); - int code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam); + int /*long*/ code = OS.DefWindowProc (handle, OS.WM_UPDATEUISTATE, wParam, lParam); return new LRESULT (code); } return result; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Link.d --- a/dwt/widgets/Link.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Link.d Sat May 17 17:34:28 2008 +0200 @@ -92,6 +92,34 @@ WNDCLASS lpWndClass; OS.GetClassInfo (null, LinkClass.ptr, &lpWndClass); LinkProc = lpWndClass.lpfnWndProc; + /* + * Feature in Windows. The SysLink window class + * does not include CS_DBLCLKS. This means that these + * controls will not get double click messages such as + * WM_LBUTTONDBLCLK. The fix is to register a new + * window class with CS_DBLCLKS. + * + * NOTE: Screen readers look for the exact class name + * of the control in order to provide the correct kind + * of assistance. Therefore, it is critical that the + * new window class have the same name. It is possible + * to register a local window class with the same name + * as a global class. Since bits that affect the class + * are being changed, it is possible that other native + * code, other than DWT, could create a control with + * this class name, and fail unexpectedly. + */ + auto hInstance = OS.GetModuleHandle (null); + auto hHeap = OS.GetProcessHeap (); + lpWndClass.hInstance = hInstance; + lpWndClass.style &= ~OS.CS_GLOBALCLASS; + lpWndClass.style |= OS.CS_DBLCLKS; + int byteCount = LinkClass.length * TCHAR.sizeof; + auto lpszClassName = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); + OS.MoveMemory (lpszClassName, LinkClass.ptr, byteCount); + lpWndClass.lpszClassName = lpszClassName; + OS.RegisterClass (&lpWndClass); + OS.HeapFree (hHeap, 0, lpszClassName); } else { LinkProc = null; } @@ -165,7 +193,24 @@ override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { if (handle is null) return 0; - if (LinkProc !is null) return OS.CallWindowProc (LinkProc, hwnd, msg, wParam, lParam); + if (LinkProc !is null) { + /* + * Feature in Windows. By convention, native Windows controls + * check for a non-NULL wParam, assume that it is an HDC and + * paint using that device. The SysLink control does not. + * The fix is to check for an HDC and use WM_PRINTCLIENT. + */ + switch (msg) { + case OS.WM_PAINT: + if (wParam !is 0) { + OS.SendMessage (hwnd, OS.WM_PRINTCLIENT, wParam, 0); + return 0; + } + break; + default: + } + return OS.CallWindowProc (LinkProc, hwnd, msg, wParam, lParam); + } return OS.DefWindowProc (hwnd, msg, wParam, lParam); } @@ -178,16 +223,23 @@ auto hDC = OS.GetDC (handle); auto newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); auto oldFont = OS.SelectObject (hDC, newFont); - TCHAR[] buffer = StrToTCHARs (getCodePage (), parse (text)); - RECT rect; - int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX; - if (wHint !is DWT.DEFAULT) { - flags |= OS.DT_WORDBREAK; - rect.right = wHint; + if (text.length > 0) { + TCHAR[] buffer = StrToTCHARs (getCodePage (), parse (text)); + RECT rect; + int flags = OS.DT_CALCRECT | OS.DT_NOPREFIX; + if (wHint !is DWT.DEFAULT) { + flags |= OS.DT_WORDBREAK; + rect.right = wHint; + } + OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags); + width = rect.right - rect.left; + height = rect.bottom; + } else { + TEXTMETRIC lptm; + OS.GetTextMetrics (hDC, &lptm); + width = 0; + height = lptm.tmHeight; } - OS.DrawText (hDC, buffer.ptr, buffer.length, &rect, flags); - width = rect.right - rect.left; - height = rect.bottom; if (newFont !is null) OS.SelectObject (hDC, oldFont); OS.ReleaseDC (handle, hDC); } else { @@ -527,7 +579,7 @@ } if (start < length_) { int tmp = parseMnemonics (buffer, start, tagStart, result); - int mnemonic = parseMnemonics (buffer, linkStart, index, result); + int mnemonic = parseMnemonics (buffer, Math.max (tagStart, linkStart), length_, result); if (mnemonic is -1) mnemonic = tmp; mnemonics [linkIndex] = mnemonic; } else { @@ -726,7 +778,7 @@ * This allows the application to cancel an operation that is normally * performed in WM_KEYDOWN from WM_CHAR. */ - int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); return new LRESULT (code); default: } @@ -738,7 +790,8 @@ override LRESULT WM_GETDLGCODE (int wParam, int lParam) { LRESULT result = super.WM_GETDLGCODE (wParam, lParam); if (result !is null) return result; - int index, count, code = 0; + int index, count; + int /*long*/ code = 0; if (OS.COMCTL32_MAJOR >= 6) { LITEM item; item.mask = OS.LIF_ITEMINDEX | OS.LIF_STATE; @@ -772,7 +825,7 @@ override LRESULT WM_GETFONT (int wParam, int lParam) { LRESULT result = super.WM_GETFONT (wParam, lParam); if (result !is null) return result; - int code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_GETFONT, wParam, lParam); if (code !is 0) return new LRESULT (code); if (font is null) font = defaultFont (); return new LRESULT ( cast(int) font); @@ -810,8 +863,8 @@ if (result is LRESULT.ZERO) return result; if (OS.COMCTL32_MAJOR < 6) { if (focusIndex !is -1) setFocus (); - int x = lParam & 0xFFFF; - int y = lParam >> 16; + int x = OS.GET_X_LPARAM (lParam); + int y = OS.GET_Y_LPARAM (lParam); int offset = layout.getOffset (x, y, null); int oldSelectionX = selection.x; int oldSelectionY = selection.y; @@ -848,8 +901,8 @@ if (result is LRESULT.ZERO) return result; if (OS.COMCTL32_MAJOR < 6) { if (mouseDownIndex is -1) return result; - int x = lParam & 0xFFFF; - int y = lParam >> 16; + int x = OS.GET_X_LPARAM (lParam); + int y = OS.GET_Y_LPARAM (lParam); Rectangle [] rects = getRectangles (mouseDownIndex); for (int i = 0; i < rects.length; i++) { Rectangle rect = rects [i]; @@ -865,11 +918,25 @@ return result; } +override LRESULT WM_NCHITTEST (int wParam, int lParam) { + LRESULT result = super.WM_NCHITTEST (wParam, lParam); + if (result !is null) return result; + + /* + * Feature in Windows. For WM_NCHITTEST, the Syslink window proc + * returns HTTRANSPARENT when mouse is over plain text. The fix is + * to always return HTCLIENT. + */ + if (OS.COMCTL32_MAJOR >= 6) return new LRESULT (OS.HTCLIENT); + + return result; +} + override LRESULT WM_MOUSEMOVE (int wParam, int lParam) { LRESULT result = super.WM_MOUSEMOVE (wParam, lParam); if (OS.COMCTL32_MAJOR < 6) { - int x = lParam & 0xFFFF; - int y = lParam >> 16; + int x = OS.GET_X_LPARAM (lParam); + int y = OS.GET_Y_LPARAM (lParam); if (OS.GetKeyState (OS.VK_LBUTTON) < 0) { int oldSelection = selection.y; selection.y = layout.getOffset (x, y, null); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/List.d --- a/dwt/widgets/List.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/List.d Sat May 17 17:34:28 2008 +0200 @@ -202,7 +202,27 @@ override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { if (handle is null) return 0; - return OS.CallWindowProc (ListProc, hwnd, msg, wParam, lParam); + bool redraw = false; + switch (msg) { + case OS.WM_HSCROLL: + case OS.WM_VSCROLL: { + redraw = findImageControl () !is null && drawCount is 0 && OS.IsWindowVisible (handle); + if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); + break; + } + } + int /*long*/ code = OS.CallWindowProc (ListProc, hwnd, msg, wParam, lParam); + switch (msg) { + case OS.WM_HSCROLL: + case OS.WM_VSCROLL: { + if (redraw) { + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); + OS.InvalidateRect (handle, null, true); + } + break; + } + } + return code; } static int checkStyle (int style) { @@ -1203,8 +1223,8 @@ for (int i=0; i= 0) { + int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); + if ((bits & OS.LBS_EXTENDEDSEL) !is 0) { + switch (wParam) { + case OS.VK_SPACE: { + int index = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0); + int code = OS.SendMessage (handle, OS.LB_GETSEL, index, 0); + if (code is OS.LB_ERR) break; + OS.SendMessage (handle, OS.LB_SETSEL, code !is 0 ? 0 : 1, index); + OS.SendMessage (handle, OS.LB_SETANCHORINDEX, index, 0); + postEvent (DWT.Selection); + return LRESULT.ZERO; + } + } + } + } + return result; +} + +override LRESULT WM_KEYDOWN (int /*long*/ wParam, int /*long*/ lParam) { + LRESULT result = super.WM_KEYDOWN (wParam, lParam); + if (result !is null) return result; + /* + * Feature in Windows. The Windows list box does not implement + * the control key interface for multi-select list boxes, making + * it inaccessible from the keyboard. The fix is to implement + * the key processing. + */ + if (OS.GetKeyState (OS.VK_CONTROL) < 0 && OS.GetKeyState (OS.VK_SHIFT) >= 0) { + int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); + if ((bits & OS.LBS_EXTENDEDSEL) !is 0) { + int location = -1; + switch (wParam) { + case OS.VK_SPACE: { + /* + * Ensure that the window proc does not process VK_SPACE + * so that it can be handled in WM_CHAR. This allows the + * application to cancel an operation that is normally + * performed in WM_KEYDOWN from WM_CHAR. + */ + return LRESULT.ZERO; + } + case OS.VK_UP: + case OS.VK_DOWN: { + int index = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0); + location = Math.max (0, index + ((wParam) is OS.VK_UP ? -1 : 1)); + break; + } + case OS.VK_PRIOR: { + int index = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0); + int topIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0); + if (index !is topIndex) { + location = topIndex; + } else { + forceResize (); + RECT rect; + OS.GetClientRect (handle, &rect); + int itemHeight = OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0); + int pageSize = Math.max (2, (rect.bottom / itemHeight)); + location = Math.max (0, topIndex - (pageSize - 1)); + } + break; + } + case OS.VK_NEXT: { + int index = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0); + int topIndex = OS.SendMessage (handle, OS.LB_GETTOPINDEX, 0, 0); + forceResize (); + RECT rect; + OS.GetClientRect (handle, &rect); + int itemHeight = OS.SendMessage (handle, OS.LB_GETITEMHEIGHT, 0, 0); + int pageSize = Math.max (2, (rect.bottom / itemHeight)); + int bottomIndex = topIndex + pageSize - 1; + if (index !is bottomIndex) { + location = bottomIndex; + } else { + location = bottomIndex + pageSize - 1; + } + int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0); + if (count !is OS.LB_ERR) location = Math.min (count - 1, location); + break; + } + case OS.VK_HOME: { + location = 0; + break; + } + case OS.VK_END: { + int count = OS.SendMessage (handle, OS.LB_GETCOUNT, 0, 0); + if (count is OS.LB_ERR) break; + location = count - 1; + break; + } + } + if (location !is -1) { + OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0); + OS.SendMessage (handle, OS.LB_SETCARETINDEX, location, 0); + return LRESULT.ZERO; + } + } + } + + /* + * Feature in Windows. When the user changes focus using + * the keyboard, the focus indicator does not draw. The + * fix is to update the UI state for the control whenever + * the focus indicator changes as a result of something + * the user types. + */ + int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); + if ((uiState & OS.UISF_HIDEFOCUS) !is 0) { + int oldIndex = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0); + int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); + int newIndex = OS.SendMessage (handle, OS.LB_GETCARETINDEX, 0, 0); + if (oldIndex !is newIndex) { + OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0); + /* + * Bug in Windows. When the WM_CHANGEUISTATE is used + * to update the UI state for a list that has been + * selected using Shift+Arrow, the focus indicator + * has pixel corruption. The fix is to redraw the + * focus item. + */ + RECT itemRect; + OS.SendMessage (handle, OS.LB_GETITEMRECT, newIndex, &itemRect); + OS.InvalidateRect (handle, &itemRect, true); + } + return new LRESULT (code); + } + return result; +} + +override LRESULT WM_SIZE (int /*long*/ wParam, int /*long*/ lParam) { /* * Bug in Windows. If the top index is changed while the * list is being resized, Windows does not redraw properly @@ -1561,7 +1720,7 @@ } override LRESULT wmCommandChild (int wParam, int lParam) { - int code = wParam >> 16; + int code = OS.HIWORD (wParam); switch (code) { case OS.LBN_SELCHANGE: postEvent (DWT.Selection); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Menu.d --- a/dwt/widgets/Menu.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Menu.d Sat May 17 17:34:28 2008 +0200 @@ -89,6 +89,11 @@ * Constructs a new instance of this class given its parent, * and sets the style for the instance so that the instance * will be a popup menu on the given parent's shell. + *

    + * After constructing a menu, it can be set into its parent + * using parent.setMenu(menu). In this case, the parent may + * be any control in the same widget tree as the parent. + *

    * * @param parent a control which will be the parent of the new instance (cannot be null) * @@ -120,6 +125,9 @@ * of those DWT style constants. The class description * lists the style constants that are applicable to the class. * Style bits are also inherited from superclasses. + *

    + * After constructing a menu or menuBar, it can be set into its parent + * using parent.setMenu(menu) or parent.setMenuBar(menuBar). *

    * * @param parent a decorations control which will be the parent of the new instance (cannot be null) @@ -148,6 +156,10 @@ * (which must be a Menu) and sets the style * for the instance so that the instance will be a drop-down * menu on the given parent's parent. + *

    + * After constructing a drop-down menu, it can be set into its parentMenu + * using parentMenu.setMenu(menu). + *

    * * @param parentMenu a menu which will be the parent of the new instance (cannot be null) * @@ -172,6 +184,10 @@ * (which must be a MenuItem) and sets the style * for the instance so that the instance will be a drop-down * menu on the given parent's parent menu. + *

    + * After constructing a drop-down menu, it can be set into its parentItem + * using parentItem.setMenu(menu). + *

    * * @param parentItem a menu item which will be the parent of the new instance (cannot be null) * @@ -227,8 +243,8 @@ int nX = x, nY = y; if (!hasLocation) { int pos = OS.GetMessagePos (); - nX = cast(short) (pos & 0xFFFF); - nY = cast(short) (pos >> 16); + nX = OS.GET_X_LPARAM (pos); + nY = OS.GET_Y_LPARAM (pos); } /* * Feature in Windows. It is legal use TrackPopupMenu() @@ -238,14 +254,14 @@ * that the menu has been closed. This is not strictly a * bug but leads to unwanted behavior when application code * assumes that every WM_INITPOPUPMENU will eventually result - * in a WM_MENUSELECT, wParam=0xFFFF0000, lParam=0 to indicate - * that the menu has been closed. The fix is to detect the - * case when TrackPopupMenu() fails and the number of items in + * in a WM_MENUSELECT, wParam=MAKEWPARAM (0, 0xFFFF), lParam=0 to + * indicate that the menu has been closed. The fix is to detect + * the case when TrackPopupMenu() fails and the number of items in * the menu is zero and issue a fake WM_MENUSELECT. */ bool success = cast(bool) OS.TrackPopupMenu (handle, flags, nX, nY, 0, hwndParent, null); if (!success && GetMenuItemCount (handle) is 0) { - OS.SendMessage (hwndParent, OS.WM_MENUSELECT, 0xFFFF0000, 0); + OS.SendMessage (hwndParent, OS.WM_MENUSELECT, OS.MAKEWPARAM (0, 0xFFFF), 0); } } else { OS.SendMessage (hwndParent, OS.WM_CANCELMODE, 0, 0); @@ -385,7 +401,7 @@ /* Set first item */ if (nToolBarId is ID_SPMM || nToolBarId is ID_SPMB) { - int hMenu = OS.SendMessage (hwndCB, OS.SHCMBM_GETSUBMENU, 0, ID_SPSOFTKEY0); + int /*long*/ hMenu = OS.SendMessage (hwndCB, OS.SHCMBM_GETSUBMENU, 0, ID_SPSOFTKEY0); /* Remove the item from the resource file */ OS.RemoveMenu (hMenu, 0, OS.MF_BYPOSITION); Menu menu = new Menu (parent, DWT.DROP_DOWN, hMenu); @@ -398,7 +414,7 @@ /* Set second item */ if (nToolBarId is ID_SPMM || nToolBarId is ID_SPBM) { - int hMenu = OS.SendMessage (hwndCB, OS.SHCMBM_GETSUBMENU, 0, ID_SPSOFTKEY1); + int /*long*/ hMenu = OS.SendMessage (hwndCB, OS.SHCMBM_GETSUBMENU, 0, ID_SPSOFTKEY1); OS.RemoveMenu (hMenu, 0, OS.MF_BYPOSITION); Menu menu = new Menu (parent, DWT.DROP_DOWN, hMenu); item = new MenuItem (this, menu, DWT.CASCADE, 1); @@ -414,7 +430,7 @@ * a result, Shell on WinCE SP must use the class Dialog. */ int dwMask = OS.SHMBOF_NODEFAULT | OS.SHMBOF_NOTIFY; - int lParam = dwMask << 16 | dwMask; + int /*long*/ lParam = OS.MAKELPARAM (dwMask, dwMask); OS.SendMessage (hwndCB, OS.SHCMBM_OVERRIDEKEY, OS.VK_ESCAPE, lParam); return; } @@ -493,7 +509,8 @@ MENUITEMINFO info; info.cbSize = MENUITEMINFO.sizeof; info.fMask = OS.MIIM_ID | OS.MIIM_TYPE | OS.MIIM_DATA; - info.wID = info.dwItemData = item.id; + info.wID = item.id; + info.dwItemData = item.id; info.fType = item.widgetStyle (); info.dwTypeData = pszText; success = cast(bool) OS.InsertMenuItem (handle, index, true, &info); @@ -583,6 +600,7 @@ } override void destroyWidget () { + MenuItem cascade = this.cascade; HMENU hMenu = handle; HWND hCB = hwndCB; releaseHandle (); @@ -591,7 +609,11 @@ OS.CommandBar_Destroy (hCB); } } else { - if (hMenu !is null) OS.DestroyMenu (hMenu); + if (cascade !is null) { + if (!OS.IsSP) cascade.setMenu (null, true); + } else { + if (hMenu !is null) OS.DestroyMenu (hMenu); + } } } @@ -1116,7 +1138,7 @@ override void releaseHandle () { super.releaseHandle (); handle = null; - hwndCB = null; + cascade = null; } override void releaseChildren (bool destroy) { @@ -1136,7 +1158,6 @@ override void releaseParent () { super.releaseParent (); - if (cascade !is null) cascade.releaseMenu (); if ((style & DWT.BAR) !is 0) { display.removeBar (this); if (this is parent.menuBar) { @@ -1163,7 +1184,6 @@ } if (parent !is null) parent.removeMenu (this); parent = null; - cascade = null; } /** diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/MenuItem.d --- a/dwt/widgets/MenuItem.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/MenuItem.d Sat May 17 17:34:28 2008 +0200 @@ -279,10 +279,10 @@ releaseHandle (); } -void fillAccel (ACCEL* accel) { - accel.fVirt = 0; - accel.cmd = accel.key = 0; - if (accelerator is 0 || !getEnabled ()) return; +bool fillAccel (ACCEL* accel) { + accel.cmd = accel.key = accel.fVirt = 0; + if (accelerator is 0 || !getEnabled ()) return false; + if ((accelerator & DWT.COMMAND) !is 0) return false; int fVirt = OS.FVIRTKEY; int key = accelerator & DWT.KEY_MASK; auto vKey = Display.untranslateKey (key); @@ -300,7 +300,7 @@ case 127: key = OS.VK_DELETE; break; default: { key = Display.wcsToMbcs (cast(char) key); - if (key is 0) return; + if (key is 0) return false; static if (OS.IsWinCE) { key = cast(int) OS.CharUpper (cast(TCHAR*) key); } else { @@ -320,6 +320,7 @@ if ((accelerator & DWT.ALT) !is 0) accel.fVirt |= OS.FALT; if ((accelerator & DWT.SHIFT) !is 0) accel.fVirt |= OS.FSHIFT; if ((accelerator & DWT.CONTROL) !is 0) accel.fVirt |= OS.FCONTROL; + return true; } void fixMenus (Decorations newParent) { @@ -428,6 +429,15 @@ OS.SendMessage (hwndCB, OS.TB_GETBUTTONINFO, id, &info); return (info.fsState & OS.TBSTATE_ENABLED) !is 0; } + /* + * Feature in Windows. For some reason, when the menu item + * is a separator, GetMenuItemInfo() always indicates that + * the item is not enabled. The fix is to track the enabled + * state for separators. + */ + if ((style & DWT.SEPARATOR) !is 0) { + return (state & DISABLED) is 0; + } auto hMenu = parent.handle; MENUITEMINFO info; info.cbSize = MENUITEMINFO.sizeof; @@ -543,11 +553,6 @@ id = -1; } -void releaseMenu () { - if (!OS.IsSP) setMenu (null); - menu = null; -} - override void releaseParent () { super.releaseParent (); if (menu !is null) menu.dispose (); @@ -695,6 +700,19 @@ if (enabled) info.fsState |= OS.TBSTATE_ENABLED; OS.SendMessage (hwndCB, OS.TB_SETBUTTONINFO, id, &info); } else { + /* + * Feature in Windows. For some reason, when the menu item + * is a separator, GetMenuItemInfo() always indicates that + * the item is not enabled. The fix is to track the enabled + * state for separators. + */ + if ((style & DWT.SEPARATOR) !is 0) { + if (enabled) { + state &= ~DISABLED; + } else { + state |= DISABLED; + } + } auto hMenu = parent.handle; static if (OS.IsWinCE) { int index = parent.indexOf (this); @@ -756,7 +774,7 @@ super.setImage (image); static if (OS.IsWinCE) { if ((OS.IsPPC || OS.IsSP) && parent.hwndCB !is null) { - int hwndCB = parent.hwndCB; + int /*long*/ hwndCB = parent.hwndCB; TBBUTTONINFO info; info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_IMAGE; @@ -825,6 +843,10 @@ error (DWT.ERROR_INVALID_PARENT); } } + setMenu (menu, false); +} + +void setMenu (Menu menu, bool dispose) { /* Assign the new menu */ Menu oldMenu = this.menu; @@ -841,14 +863,6 @@ } if (OS.IsSP) error (DWT.ERROR_CANNOT_SET_MENU); } else { - /* - * Feature in Windows. When SetMenuItemInfo () is used to - * set a submenu and the menu item already has a submenu, - * Windows destroys the previous menu. This is undocumented - * and unexpected but not necessarily wrong. The fix is to - * remove the item with RemoveMenu () which does not destroy - * the submenu and then insert the item with InsertMenuItem (). - */ HMENU hMenu = parent.handle; MENUITEMINFO info; info.cbSize = MENUITEMINFO.sizeof; @@ -859,41 +873,33 @@ index++; } if (info.dwItemData !is id) return; - bool restoreBitmap = false, success = false; - + int cch = 128; + auto hHeap = OS.GetProcessHeap (); + int byteCount = cch * TCHAR.sizeof; + auto pszText = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); + info.fMask = OS.MIIM_STATE | OS.MIIM_ID | OS.MIIM_DATA; /* * Bug in Windows. When GetMenuItemInfo() is used to get the text, * for an item that has a bitmap set using MIIM_BITMAP, the text is * not returned. This means that when SetMenuItemInfo() is used to * set the submenu and the current menu state, the text is lost. - * The fix is to temporarily remove the bitmap and restore it after - * the text and submenu have been set. + * The fix is use MIIM_BITMAP and MIIM_STRING. */ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) { - info.fMask = OS.MIIM_BITMAP; - OS.GetMenuItemInfo (hMenu, index, true, &info); - restoreBitmap = info.hbmpItem !is null || parent.foreground !is -1; - if (restoreBitmap) { - info.hbmpItem = null; - success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info); - } + info.fMask |= OS.MIIM_BITMAP | OS.MIIM_STRING; + } else { + info.fMask |= OS.MIIM_TYPE; } - - int cch = 128; - auto hHeap = OS.GetProcessHeap (); - int byteCount = cch * TCHAR.sizeof; - auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); - info.fMask = OS.MIIM_STATE | OS.MIIM_ID | OS.MIIM_TYPE | OS.MIIM_DATA; info.dwTypeData = pszText; info.cch = cch; - success = cast(bool) OS.GetMenuItemInfo (hMenu, index, true, &info); + bool success = cast(bool) OS.GetMenuItemInfo (hMenu, index, true, &info); if (menu !is null) { menu.cascade = this; info.fMask |= OS.MIIM_SUBMENU; info.hSubMenu = menu.handle; } - OS.RemoveMenu (hMenu, index, OS.MF_BYPOSITION); - static if (OS.IsWinCE) { + if (OS.IsWinCE) { + OS.RemoveMenu (hMenu, index, OS.MF_BYPOSITION); /* * On WinCE, InsertMenuItem() is not available. The fix is to * use SetMenuItemInfo() but this call does not set the menu item @@ -901,17 +907,17 @@ * the item, SetMenuItemInfo() to set the string and EnableMenuItem() * and CheckMenuItem() to set the state. */ - int uIDNewItem = id; + int /*long*/ uIDNewItem = id; int uFlags = OS.MF_BYPOSITION; if (menu !is null) { uFlags |= OS.MF_POPUP; - uIDNewItem = menu.handle; + uIDNewItem = cast(int)menu.handle; } - TCHAR lpNewItem = new TCHAR (0, " ", true); - success = OS.InsertMenu (hMenu, index, uFlags, uIDNewItem, lpNewItem); + TCHAR[] lpNewItem = StrToTCHARs (0, " ", true); + success = OS.InsertMenu (hMenu, index, uFlags, uIDNewItem, lpNewItem.ptr) !is 0; if (success) { info.fMask = OS.MIIM_DATA | OS.MIIM_TYPE; - success = OS.SetMenuItemInfo (hMenu, index, true, info); + success = OS.SetMenuItemInfo (hMenu, index, true, &info) !is 0; if ((info.fState & (OS.MFS_DISABLED | OS.MFS_GRAYED)) !is 0) { OS.EnableMenuItem (hMenu, index, OS.MF_BYPOSITION | OS.MF_GRAYED); } @@ -920,26 +926,19 @@ } } } else { - success = cast(bool) OS.InsertMenuItem (hMenu, index, true, &info); - /* - * Restore the bitmap that was removed to work around a problem - * in GetMenuItemInfo() and menu items that have bitmaps set with - * MIIM_BITMAP. - */ - if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) { - if (restoreBitmap) { - info.fMask = OS.MIIM_BITMAP; - if (parent.foreground !is -1) { - info.hbmpItem = OS.HBMMENU_CALLBACK; - } else { - if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { - info.hbmpItem = hBitmap; - } else { - info.hbmpItem = OS.HBMMENU_CALLBACK; - } - } - success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info); - } + if (dispose || oldMenu is null) { + success = cast(bool) OS.SetMenuItemInfo (hMenu, index, true, &info); + } else { + /* + * Feature in Windows. When SetMenuItemInfo () is used to + * set a submenu and the menu item already has a submenu, + * Windows destroys the previous menu. This is undocumented + * and unexpected but not necessarily wrong. The fix is to + * remove the item with RemoveMenu () which does not destroy + * the submenu and then insert the item with InsertMenuItem (). + */ + OS.RemoveMenu (hMenu, index, OS.MF_BYPOSITION); + success = OS.InsertMenuItem (hMenu, index, true, &info) !is 0; } } if (pszText !is null ) OS.HeapFree (hHeap, 0, pszText); @@ -1085,49 +1084,24 @@ info.cbSize = MENUITEMINFO.sizeof; auto hMenu = parent.handle; - /* - * Bug in Windows 2000. For some reason, when MIIM_TYPE is set - * on a menu item that also has MIIM_BITMAP, the MIIM_TYPE clears - * the MIIM_BITMAP style. The fix is to reset both MIIM_BITMAP. - * Note, this does not happen on Windows 98. - */ - bool restoreBitmap = false; - if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) { - info.fMask = OS.MIIM_BITMAP; - OS.GetMenuItemInfo (hMenu, id, false, &info); - restoreBitmap = info.hbmpItem !is null || parent.foreground !is -1; - } - /* Use the character encoding for the default locale */ TCHAR[] buffer = StrToTCHARs (0, string, true); int byteCount = buffer.length * TCHAR.sizeof; - pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); + pszText = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory (pszText, buffer.ptr, byteCount); - info.fMask = OS.MIIM_TYPE; - info.fType = widgetStyle (); - info.dwTypeData = pszText; - success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info); - /* - * Restore the bitmap that was removed to work around a problem - * in GetMenuItemInfo() and menu items that have bitmaps set with - * MIIM_BITMAP. + * Bug in Windows 2000. For some reason, when MIIM_TYPE is set + * on a menu item that also has MIIM_BITMAP, the MIIM_TYPE clears + * the MIIM_BITMAP style. The fix is to use MIIM_STRING. */ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (4, 10)) { - if (restoreBitmap) { - info.fMask = OS.MIIM_BITMAP; - if (parent.foreground !is -1) { - info.hbmpItem = OS.HBMMENU_CALLBACK; - } else { - if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { - info.hbmpItem = hBitmap; - } else { - info.hbmpItem = OS.HBMMENU_CALLBACK; - } - } - success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info); - } + info.fMask = OS.MIIM_STRING; + } else { + info.fMask = OS.MIIM_TYPE; + info.fType = widgetStyle (); } + info.dwTypeData = pszText; + success = cast(bool) OS.SetMenuItemInfo (hMenu, id, false, &info); } if (pszText !is null) OS.HeapFree (hHeap, 0, pszText); if (!success) error (DWT.ERROR_CANNOT_SET_TEXT); @@ -1151,7 +1125,7 @@ return bits | OS.MFT_STRING; } -LRESULT wmCommandChild (int wParam, int lParam) { +LRESULT wmCommandChild (int /*long*/ wParam, int /*long*/ lParam) { if ((style & DWT.CHECK) !is 0) { setSelection (!getSelection ()); } else { @@ -1169,7 +1143,7 @@ return null; } -LRESULT wmDrawChild (int wParam, int lParam) { +LRESULT wmDrawChild (int /*long*/ wParam, int /*long*/ lParam) { DRAWITEMSTRUCT* struct_ = cast(DRAWITEMSTRUCT*)lParam; //OS.MoveMemory (struct_, lParam, DRAWITEMSTRUCT.sizeof); if (image !is null) { @@ -1192,7 +1166,7 @@ return null; } -LRESULT wmMeasureChild (int wParam, int lParam) { +LRESULT wmMeasureChild (int /*long*/ wParam, int /*long*/ lParam) { MEASUREITEMSTRUCT* struct_ = cast(MEASUREITEMSTRUCT*)lParam; //OS.MoveMemory (struct_, lParam, MEASUREITEMSTRUCT.sizeof); int width = 0, height = 0; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/MessageBox.d --- a/dwt/widgets/MessageBox.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/MessageBox.d Sat May 17 17:34:28 2008 +0200 @@ -42,6 +42,9 @@ *

    */ public class MessageBox : Dialog { + + alias Dialog.checkStyle checkStyle; + String message = ""; private bool allowNullParent = false; @@ -86,7 +89,7 @@ * */ public this (Shell parent, int style) { - super (parent, checkStyle (style)); + super (parent, checkStyle (parent, checkStyle (style))); checkSubclass (); } @@ -95,8 +98,7 @@ +/ public this (int style) { allowNullParent = true; - super (parent, checkStyle (style)); - checkSubclass (); + this( null, style ); } // PORT // actually, the parent can be null @@ -107,7 +109,6 @@ } static int checkStyle (int style) { - if ((style & (DWT.PRIMARY_MODAL | DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) is 0) style |= DWT.APPLICATION_MODAL; int mask = (DWT.YES | DWT.NO | DWT.OK | DWT.CANCEL | DWT.ABORT | DWT.RETRY | DWT.IGNORE); int bits = style & mask; if (bits is DWT.OK || bits is DWT.CANCEL || bits is (DWT.OK | DWT.CANCEL)) return style; @@ -200,12 +201,12 @@ * parent be temporarily modal. */ HWND hwndOwner = parent !is null ? parent.handle : null; - Shell oldModal = null; + Dialog oldModal = null; Display display = null; if ((bits & OS.MB_TASKMODAL) !is 0) { display = ( allowNullParent && parent is null ) ? Display.getCurrent() : parent.getDisplay (); - oldModal = display.getModalDialogShell (); - display.setModalDialogShell (parent); + oldModal = display.getModalDialog (); + display.setModalDialog (this); } /* Open the message box */ @@ -216,7 +217,7 @@ /* Clear the temporarily dialog modal parent */ if ((bits & OS.MB_TASKMODAL) !is 0) { - display.setModalDialogShell (oldModal); + display.setModalDialog (oldModal); } /* diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Monitor.d --- a/dwt/widgets/Monitor.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Monitor.d Sat May 17 17:34:28 2008 +0200 @@ -53,7 +53,8 @@ /** * Returns a rectangle describing the receiver's size and location - * relative to its device. + * relative to its device. Note that on multi-monitor systems the + * origin can be negative. * * @return the receiver's bounding rectangle */ diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/ProgressBar.d --- a/dwt/widgets/ProgressBar.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/ProgressBar.d Sat May 17 17:34:28 2008 +0200 @@ -65,7 +65,7 @@ ProgressBarProc = lpWndClass.lpfnWndProc; /* * Feature in Windows. The progress bar window class - * does not include CS_DBLCLKS. This mean that these + * does not include CS_DBLCLKS. This means that these * controls will not get double click messages such as * WM_LBUTTONDBLCLK. The fix is to register a new * window class with CS_DBLCLKS. @@ -210,6 +210,32 @@ return OS.SendMessage (handle, OS.PBM_GETPOS, 0, 0); } +/** + * Returns the state of the receiver. The value will be one of + * NORMAL, ERROR or PAUSED. + * + * @return the state + * + * @exception DWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.4 + */ +public int getState () { + checkWidget (); + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + int state = OS.SendMessage (handle, OS.PBM_GETSTATE, 0, 0); + switch (state) { + case OS.PBST_NORMAL: return DWT.NORMAL; + case OS.PBST_ERROR: return DWT.ERROR; + case OS.PBST_PAUSED: return DWT.PAUSED; + } + } + return DWT.NORMAL; +} + override void releaseWidget () { super.releaseWidget (); stopTimer (); @@ -303,7 +329,52 @@ */ public void setSelection (int value) { checkWidget (); + /* + * Feature in Vista. When the progress bar is not in + * a normal state, PBM_SETPOS does not set the position. + * This is undocumented. The fix is to temporarily + * set the state to PBST_NORMAL, set the position, then + * reset the state. + */ + int /*long*/ state = 0; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + state = OS.SendMessage (handle, OS.PBM_GETSTATE, 0, 0); + OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_NORMAL, 0); + } OS.SendMessage (handle, OS.PBM_SETPOS, value, 0); + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + OS.SendMessage (handle, OS.PBM_SETSTATE, state, 0); + } +} + +/** + * Sets the state of the receiver. The state is be one of + * NORMAL, ERROR or PAUSED. + * + * @param state the new state + * + * @exception DWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.4 + */ +public void setState (int state) { + checkWidget (); + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + switch (state) { + case DWT.NORMAL: + OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_NORMAL, 0); + break; + case DWT.ERROR: + OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_ERROR, 0); + break; + case DWT.PAUSED: + OS.SendMessage (handle, OS.PBM_SETSTATE, OS.PBST_PAUSED, 0); + break; + } + } } override int widgetStyle () { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Sash.d --- a/dwt/widgets/Sash.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Sash.d Sat May 17 17:34:28 2008 +0200 @@ -281,8 +281,7 @@ /* Compute the banding rectangle */ auto hwndTrack = parent.handle; POINT pt; - pt.x = cast(short) (lParam & 0xFFFF); - pt.y = cast(short) (lParam >> 16); + OS.POINTSTOPOINT (pt, lParam); RECT rect; OS.GetWindowRect (handle, &rect); OS.MapWindowPoints (handle, null, &pt, 1); @@ -365,8 +364,7 @@ /* Compute the banding rectangle */ POINT pt; - pt.x = cast(short) (lParam & 0xFFFF); - pt.y = cast(short) (lParam >> 16); + OS.POINTSTOPOINT (pt, lParam); auto hwndTrack = parent.handle; OS.MapWindowPoints (handle, hwndTrack, &pt, 1); RECT rect, clientRect; @@ -417,7 +415,7 @@ override LRESULT WM_SETCURSOR (int wParam, int lParam) { LRESULT result = super.WM_SETCURSOR (wParam, lParam); if (result !is null) return result; - int hitTest = lParam & 0xFFFF; + int hitTest = cast(short) OS.LOWORD (lParam); if (hitTest is OS.HTCLIENT) { HCURSOR hCursor; if ((style & DWT.HORIZONTAL) !is 0) { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Scale.d --- a/dwt/widgets/Scale.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Scale.d Sat May 17 17:34:28 2008 +0200 @@ -50,7 +50,7 @@ alias Control.setBackgroundImage setBackgroundImage; alias Control.windowProc windowProc; - bool ignoreResize; + bool ignoreResize, ignoreSelection; private static /+const+/ WNDPROC TrackBarProc; static const TCHAR[] TrackBarClass = OS.TRACKBAR_CLASS; @@ -68,7 +68,7 @@ TrackBarProc = lpWndClass.lpfnWndProc; /* * Feature in Windows. The track bar window class - * does not include CS_DBLCLKS. This mean that these + * does not include CS_DBLCLKS. This means that these * controls will not get double click messages such as * WM_LBUTTONDBLCLK. The fix is to register a new * window class with CS_DBLCLKS. @@ -248,7 +248,7 @@ */ public int getMinimum () { checkWidget (); - return OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0); + return cast(int)OS.SendMessage (handle, OS.TBM_GETRANGEMIN, 0, 0); } /** @@ -334,6 +334,33 @@ ignoreResize = false; } +void setBounds (int x, int y, int width, int height, int flags, bool defer) { + /* + * Bug in Windows. If SetWindowPos() is called on a + * track bar with either SWP_DRAWFRAME, a new size, + * or both during mouse down, the track bar posts a + * WM_MOUSEMOVE message when the mouse has not moved. + * The window proc for the track bar uses WM_MOUSEMOVE + * to issue WM_HSCROLL or WM_SCROLL events to notify + * the application that the slider has changed. The + * end result is that when the user requests a page + * scroll and the application resizes the track bar + * during the change notification, continuous stream + * of WM_MOUSEMOVE messages are generated and the + * thumb moves to the mouse position rather than + * scrolling by a page. The fix is to clear the + * SWP_DRAWFRAME flag. + * + * NOTE: There is no fix for the WM_MOUSEMOVE that + * is generated by a new size. Clearing SWP_DRAWFRAME + * does not fix the problem. However, it is unlikely + * that the programmer will resize the control during + * mouse down. + */ + flags &= ~OS.SWP_DRAWFRAME; + super.setBounds (x, y, width, height, flags, true); +} + /** * Sets the amount that the receiver's value will be * modified by when the up/down (or right/left) arrows @@ -452,6 +479,34 @@ } override LRESULT WM_PAINT (int wParam, int lParam) { + LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam); + if (result !is null) return result; + /* + * Bug in Windows. When a track bar slider is changed + * from WM_MOUSEWHEEL, it does not always send either + * a WM_VSCROLL or M_HSCROLL to notify the application + * of the change. The fix is to detect that the selection + * has changed and that notification has not been issued + * and send the selection event. + */ + int oldPosition = OS.SendMessage (handle, OS.TBM_GETPOS, 0, 0); + ignoreSelection = true; + int /*long*/ code = callWindowProc (handle, OS.WM_MOUSEWHEEL, wParam, lParam); + ignoreSelection = false; + int newPosition = OS.SendMessage (handle, OS.TBM_GETPOS, 0, 0); + if (oldPosition !is newPosition) { + /* + * Send the event because WM_HSCROLL and WM_VSCROLL + * are sent from a modal message loop in windows that + * is active when the user is scrolling. + */ + sendEvent (DWT.Selection); + // widget could be disposed at this point + } + return new LRESULT (code); +} + +override LRESULT WM_MOUSEWHEEL (int wParam, int lParam) { /* * Bug in Windows. For some reason, when WM_CTLCOLORSTATIC * is used to implement transparency and returns a NULL brush, @@ -491,7 +546,7 @@ override LRESULT wmScrollChild (int wParam, int lParam) { /* Do nothing when scrolling is ending */ - int code = wParam & 0xFFFF; + int code = OS.LOWORD (wParam); switch (code) { case OS.TB_ENDTRACK: case OS.TB_THUMBPOSITION: @@ -499,29 +554,31 @@ default: } - Event event = new Event (); - /* - * This code is intentionally commented. The event - * detail field is not currently supported on all - * platforms. - */ -// switch (code) { -// case OS.TB_TOP: event.detail = DWT.HOME; break; -// case OS.TB_BOTTOM: event.detail = DWT.END; break; -// case OS.TB_LINEDOWN: event.detail = DWT.ARROW_DOWN; break; -// case OS.TB_LINEUP: event.detail = DWT.ARROW_UP; break; -// case OS.TB_PAGEDOWN: event.detail = DWT.PAGE_DOWN; break; -// case OS.TB_PAGEUP: event.detail = DWT.PAGE_UP; break; + if (!ignoreSelection) { + Event event = new Event (); + /* + * This code is intentionally commented. The event + * detail field is not currently supported on all + * platforms. + */ +// switch (code) { +// case OS.TB_TOP: event.detail = DWT.HOME; break; +// case OS.TB_BOTTOM: event.detail = DWT.END; break; +// case OS.TB_LINEDOWN: event.detail = DWT.ARROW_DOWN; break; +// case OS.TB_LINEUP: event.detail = DWT.ARROW_UP; break; +// case OS.TB_PAGEDOWN: event.detail = DWT.PAGE_DOWN; break; +// case OS.TB_PAGEUP: event.detail = DWT.PAGE_UP; break; // default: -// } +// } - /* - * Send the event because WM_HSCROLL and WM_VSCROLL - * are sent from a modal message loop in windows that - * is active when the user is scrolling. - */ - sendEvent (DWT.Selection, event); - // widget could be disposed at this point + /* + * Send the event because WM_HSCROLL and WM_VSCROLL + * are sent from a modal message loop in windows that + * is active when the user is scrolling. + */ + sendEvent (DWT.Selection, event); + // widget could be disposed at this point + } return null; } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/ScrollBar.d --- a/dwt/widgets/ScrollBar.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/ScrollBar.d Sat May 17 17:34:28 2008 +0200 @@ -207,7 +207,10 @@ } else { OS.ShowScrollBar (hwnd, type, false); } + parent.destroyScrollBar (style); releaseHandle (); + //This code is intentionally commented + //parent.sendEvent (DWT.Resize); } Rectangle getBounds () { @@ -433,6 +436,13 @@ */ public bool getVisible () { checkWidget(); + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) { + SCROLLBARINFO psbi; + psbi.cbSize = SCROLLBARINFO.sizeof; + int idObject = (style & DWT.VERTICAL) !is 0 ? OS.OBJID_VSCROLL : OS.OBJID_HSCROLL; + OS.GetScrollBarInfo (hwndScrollBar (), idObject, &psbi); + return (psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) is 0; + } return (state & HIDDEN) is 0; } @@ -653,7 +663,27 @@ * scroll bar operation is performed), the opposite scroll * bar draws. The fix is to hide both scroll bars. */ - if ((state & (DISABLED | HIDDEN)) !is 0) fRedraw = false; + bool barVisible = false; + bool visible = getVisible (); + + /* + * This line is intentionally commented. Currently + * always show scrollbar as being enabled and visible. + */ +// if (OS.IsWinCE) error (DWT.ERROR_NOT_IMPLEMENTED); + ScrollBar bar = null; + if (!OS.IsWinCE) { + switch (flags) { + case OS.SB_HORZ: + bar = parent.getVerticalBar (); + break; + case OS.SB_VERT: + bar = parent.getHorizontalBar (); + break; + } + barVisible = bar !is null && bar.getVisible (); + } + if (!visible || (state & DISABLED) !is 0) fRedraw = false; bool result = cast(bool) OS.SetScrollInfo (hwnd, flags, info, fRedraw); /* @@ -665,25 +695,31 @@ * is performed), the scroll bar draws. The fix is * to hide the scroll bar (again) when already hidden. */ - if ((state & HIDDEN) !is 0) { + if (!visible) { /* * This line is intentionally commented. Currently * always show scrollbar as being enabled and visible. */ // if (OS.IsWinCE) error (DWT.ERROR_NOT_IMPLEMENTED); if (!OS.IsWinCE) { - ScrollBar bar = null; - switch (flags) { - case OS.SB_HORZ: - bar = parent.getVerticalBar (); - break; - case OS.SB_VERT: - bar = parent.getHorizontalBar (); - break; - default: - } - bool both = bar !is null && !bar.getVisible (); - OS.ShowScrollBar (hwnd, both ? OS.SB_BOTH : flags, false); + OS.ShowScrollBar (hwnd, !barVisible ? OS.SB_BOTH : flags, false); + } + } + + /* + * Bug in Windows. When only one scroll bar is visible, + * and the thumb changes using SIF_RANGE or SIF_PAGE + * from being visible to hidden, the opposite scroll + * bar is incorrectly made visible. The next time the + * parent is resized (or another scroll bar operation + * is performed), the opposite scroll bar draws. The + * fix is to hide the opposite scroll bar again. + * + * NOTE: This problem only happens on Vista + */ + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + if (visible && bar !is null && !barVisible) { + OS.ShowScrollBar (hwnd, flags is OS.SB_HORZ ? OS.SB_VERT : OS.SB_HORZ, false); } } @@ -820,8 +856,7 @@ */ public void setVisible (bool visible) { checkWidget(); - bool isVisible = (state & HIDDEN) is 0; - if (isVisible is visible) return; + if (visible is getVisible ()) return; /* * On Windows CE, use SIF_DISABLENOSCROLL to show and @@ -898,11 +933,11 @@ } } -LRESULT wmScrollChild (int wParam, int lParam) { +LRESULT wmScrollChild (int /*long*/ wParam, int /*long*/ lParam) { trc(__LINE__); /* Do nothing when scrolling is ending */ - int code = wParam & 0xFFFF; + int code = OS.LOWORD (wParam); if (code is OS.SB_ENDSCROLL) return null; /* diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Scrollable.d --- a/dwt/widgets/Scrollable.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Scrollable.d Sat May 17 17:34:28 2008 +0200 @@ -12,16 +12,20 @@ *******************************************************************************/ module dwt.widgets.Scrollable; -import dwt.widgets.Widget; -import dwt.widgets.Event; -import dwt.widgets.Control; -import dwt.widgets.ScrollBar; -import dwt.widgets.Composite; import dwt.DWT; import dwt.DWTException; + import dwt.graphics.Rectangle; + import dwt.internal.win32.OS; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Decorations; +import dwt.widgets.Event; +import dwt.widgets.ScrollBar; +import dwt.widgets.Widget; + import dwt.dwthelper.utils; import tango.util.log.Trace; void trc( long line ){ @@ -149,6 +153,20 @@ if ((style & DWT.V_SCROLL) !is 0) verticalBar = createScrollBar (DWT.V_SCROLL); } +void destroyScrollBar (int type) { + auto hwnd = scrolledHandle (); + int bits = OS.GetWindowLong (hwnd, OS.GWL_STYLE); + if ((type & DWT.HORIZONTAL) !is 0) { + style &= ~DWT.H_SCROLL; + bits &= ~OS.WS_HSCROLL; + } + if ((type & DWT.VERTICAL) !is 0) { + style &= ~DWT.V_SCROLL; + bits &= ~OS.WS_VSCROLL; + } + OS.SetWindowLong (hwnd, OS.GWL_STYLE, bits); +} + /** * Returns a rectangle which describes the area of the * receiver which is capable of displaying data (that is, @@ -278,9 +296,9 @@ override LRESULT WM_MOUSEWHEEL (int wParam, int lParam) { trc(__LINE__); + int scrollRemainder = display.scrollRemainder; LRESULT result = super.WM_MOUSEWHEEL (wParam, lParam); if (result !is null) return result; - /* * Translate WM_MOUSEWHEEL to WM_VSCROLL or WM_HSCROLL. */ @@ -288,27 +306,37 @@ if ((wParam & (OS.MK_SHIFT | OS.MK_CONTROL)) !is 0) return result; bool vertical = verticalBar !is null && verticalBar.getEnabled (); bool horizontal = horizontalBar !is null && horizontalBar.getEnabled (); - int msg = (vertical) ? OS.WM_VSCROLL : (horizontal) ? OS.WM_HSCROLL : 0; + int msg = vertical ? OS.WM_VSCROLL : horizontal ? OS.WM_HSCROLL : 0; if (msg is 0) return result; - int value; - OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0); - int delta = cast(short) (wParam >> 16); - int code = 0, count = 0; - if (value is OS.WHEEL_PAGESCROLL) { - code = delta < 0 ? OS.SB_PAGEDOWN : OS.SB_PAGEUP; - count = Math.abs (delta / OS.WHEEL_DELTA); + int linesToScroll; + OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &linesToScroll, 0); + int delta = OS.GET_WHEEL_DELTA_WPARAM (wParam); + bool pageScroll = linesToScroll is OS.WHEEL_PAGESCROLL; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + ScrollBar bar = vertical ? verticalBar : horizontalBar; + SCROLLINFO info; + info.cbSize = SCROLLINFO.sizeof; + info.fMask = OS.SIF_POS; + OS.GetScrollInfo (handle, bar.scrollBarType (), &info); + if (vertical && !pageScroll) delta *= linesToScroll; + int increment = pageScroll ? bar.getPageIncrement () : bar.getIncrement (); + info.nPos -= increment * delta / OS.WHEEL_DELTA; + OS.SetScrollInfo (handle, bar.scrollBarType (), &info, true); + OS.SendMessage (handle, msg, OS.SB_THUMBPOSITION, 0); } else { - code = delta < 0 ? OS.SB_LINEDOWN : OS.SB_LINEUP; - delta = Math.abs (delta); - if (delta < OS.WHEEL_DELTA) return result; - if (msg is OS.WM_VSCROLL) { - count = value * delta / OS.WHEEL_DELTA; + int code = 0; + if (pageScroll) { + code = delta < 0 ? OS.SB_PAGEDOWN : OS.SB_PAGEUP; } else { - count = delta / OS.WHEEL_DELTA; + code = delta < 0 ? OS.SB_LINEDOWN : OS.SB_LINEUP; + if (msg is OS.WM_VSCROLL) delta *= linesToScroll; } - } - for (int i=0; i= 0) delta += scrollRemainder; + int count = Math.abs (delta) / OS.WHEEL_DELTA; + for (int i=0; i= 6 && OS.IsAppThemed ()) { + if (!OS.IsWinCE && OS.WIN32_VERSION < OS.VERSION (6, 0)) { + int bits1 = OS.GetWindowLong (hwnd, OS.GWL_STYLE); + if ((bits1 & (OS.WS_HSCROLL | OS.WS_VSCROLL)) !is 0) { + RECT windowRect; + OS.GetWindowRect (hwnd, &windowRect); + RECT trimRect; + int bits2 = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE); + OS.AdjustWindowRectEx (&trimRect, bits1, false, bits2); + bool hVisible = false, vVisible = false; + SCROLLBARINFO psbi; + psbi.cbSize = SCROLLBARINFO.sizeof; + if (OS.GetScrollBarInfo (hwnd, OS.OBJID_HSCROLL, &psbi)) { + hVisible = (psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) is 0; + } + if (OS.GetScrollBarInfo (hwnd, OS.OBJID_VSCROLL, &psbi)) { + vVisible = (psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) is 0; + } + RECT cornerRect; + cornerRect.right = windowRect.right - windowRect.left - trimRect.right; + cornerRect.bottom = windowRect.bottom - windowRect.top - trimRect.bottom; + cornerRect.left = cornerRect.right - (hVisible ? OS.GetSystemMetrics (OS.SM_CXVSCROLL) : 0); + cornerRect.top = cornerRect.bottom - (vVisible ? OS.GetSystemMetrics (OS.SM_CYHSCROLL) : 0); + if (cornerRect.left !is cornerRect.right && cornerRect.top !is cornerRect.bottom) { + auto hDC = OS.GetWindowDC (hwnd); + OS.FillRect (hDC, &cornerRect, cast(HANDLE)( OS.COLOR_BTNFACE + 1)); + Decorations shell = menuShell (); + if ((shell.style & DWT.RESIZE) !is 0) { + auto hwndScroll = shell.scrolledHandle (); + bool drawGripper = hwnd is hwndScroll; + if (!drawGripper) { + RECT shellRect; + OS.GetClientRect (hwndScroll, &shellRect); + OS.MapWindowPoints (hwndScroll, null, cast(POINT*)&shellRect, 2); + drawGripper = shellRect.right is windowRect.right && shellRect.bottom is windowRect.bottom; + } + if (drawGripper) { + OS.DrawThemeBackground (display.hScrollBarTheme(), hDC, OS.SBP_SIZEBOX, 0, &cornerRect, null); + } + } + OS.ReleaseDC (hwnd, hDC); + } + } + } + } + return result; +} + +LRESULT wmScroll (ScrollBar bar, bool update, HWND hwnd, int msg, int /*long*/ wParam, int /*long*/ lParam) { LRESULT result = null; if (update) { int type = msg is OS.WM_HSCROLL ? OS.SB_HORZ : OS.SB_VERT; @@ -382,7 +466,7 @@ info.fMask = OS.SIF_TRACKPOS | OS.SIF_POS | OS.SIF_RANGE; OS.GetScrollInfo (hwnd, type, &info); info.fMask = OS.SIF_POS; - int code = wParam & 0xFFFF; + int code = OS.LOWORD (wParam); switch (code) { case OS.SB_ENDSCROLL: return null; case OS.SB_THUMBPOSITION: @@ -419,7 +503,7 @@ } OS.SetScrollInfo (hwnd, type, &info, true); } else { - int code = callWindowProc (hwnd, msg, wParam, lParam); + int /*long*/ code = callWindowProc (hwnd, msg, wParam, lParam); result = code is 0 ? LRESULT.ZERO : new LRESULT (code); } bar.wmScrollChild (wParam, lParam); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Shell.d --- a/dwt/widgets/Shell.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Shell.d Sat May 17 17:34:28 2008 +0200 @@ -16,6 +16,7 @@ import dwt.DWTException; import dwt.events.ShellListener; import dwt.graphics.Cursor; +import dwt.graphics.GC; import dwt.graphics.Point; import dwt.graphics.Rectangle; import dwt.graphics.Region; @@ -28,6 +29,7 @@ import dwt.widgets.ToolTip; import dwt.widgets.Display; import dwt.widgets.TypedListener; +import dwt.widgets.Event; import dwt.dwthelper.utils; @@ -147,23 +149,22 @@ HANDLE balloonTipHandle_; int minWidth = DWT.DEFAULT, minHeight = DWT.DEFAULT; HBRUSH [] brushes; - bool showWithParent; + bool showWithParent, fullScreen, wasMaximized; String toolTitle, balloonTitle; HICON toolIcon; HICON balloonIcon; WNDPROC windowProc_; - Control lastActive, lockToolTipControl; + Control lastActive; static if( OS.IsWinCE ){ SHACTIVATEINFO psai; } - Region region; static /+const+/ WNDPROC ToolTipProc; static /+const+/ WNDPROC DialogProc; static if( OS.IsWinCE ){ - static const TCHAR[] DialogClass = "Dialog\0"; + static const TCHAR[] DialogClass = "Dialog\0"w; } else{ - static const TCHAR[] DialogClass = "#32770\0"; + static const TCHAR[] DialogClass = "#32770\0"w; } const static int [] SYSTEM_COLORS = [ OS.COLOR_BTNFACE, @@ -413,7 +414,8 @@ } /** - * Invokes platform specific functionality to allocate a new shell. + * Invokes platform specific functionality to allocate a new shell + * that is embedded. *

    * IMPORTANT: This method is not part of the public * API for Shell. It is marked public only so that it @@ -430,12 +432,30 @@ return new Shell (display, null, DWT.NO_TRIM, handle, true); } +/** + * Invokes platform specific functionality to allocate a new shell + * that is not embedded. + *

    + * IMPORTANT: This method is not part of the public + * API for Shell. It is marked public only so that it + * can be shared within the packages provided by DWT. It is not + * available on all platforms, and should never be called from + * application code. + *

    + * + * @param display the display for the shell + * @param handle the handle for the shell + * @return a new shell object containing the specified display and handle + * + * @since 3.3 + */ public static Shell internal_new (Display display, HWND handle) { return new Shell (display, null, DWT.NO_TRIM, handle, false); } static int checkStyle (int style) { style = Decorations.checkStyle (style); + style &= ~DWT.TRANSPARENT; int mask = DWT.SYSTEM_MODAL | DWT.APPLICATION_MODAL | DWT.PRIMARY_MODAL; int bits = style & ~mask; if ((style & DWT.SYSTEM_MODAL) !is 0) return bits | DWT.SYSTEM_MODAL; @@ -531,7 +551,7 @@ 0, OS.TOOLTIPS_CLASS.ptr, null, - OS.TTS_ALWAYSTIP | OS.TTS_BALLOON, + OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX | OS.TTS_BALLOON, OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, handle, null, @@ -539,7 +559,7 @@ null); if (balloonTipHandle_ is null) error (DWT.ERROR_NO_HANDLES); if (ToolTipProc is null) { - ToolTipProc = cast(WNDPROC) OS.GetWindowLong (balloonTipHandle_, OS.GWL_WNDPROC); + ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC); } /* * Feature in Windows. Despite the fact that the @@ -550,7 +570,7 @@ */ OS.SendMessage (balloonTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF); display.addControl (balloonTipHandle_, this); - OS.SetWindowLong (balloonTipHandle_, OS.GWL_WNDPROC, display.windowProc); + OS.SetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC, display.windowProc); } override void createHandle () { @@ -639,7 +659,7 @@ 0, OS.TOOLTIPS_CLASS.ptr, null, - OS.TTS_ALWAYSTIP, + OS.TTS_ALWAYSTIP | OS.TTS_NOPREFIX, OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, handle, null, @@ -647,7 +667,7 @@ null); if (toolTipHandle_ is null) error (DWT.ERROR_NO_HANDLES); if (ToolTipProc is null) { - ToolTipProc = cast(WNDPROC) OS.GetWindowLong (toolTipHandle_, OS.GWL_WNDPROC); + ToolTipProc = cast(WNDPROC) OS.GetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC); } /* * Feature in Windows. Despite the fact that the @@ -658,7 +678,7 @@ */ OS.SendMessage (toolTipHandle_, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF); display.addControl (toolTipHandle_, this); - OS.SetWindowLong (toolTipHandle_, OS.GWL_WNDPROC, display.windowProc); + OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, display.windowProc); } override void deregister () { @@ -864,6 +884,29 @@ /* Do nothing */ } +/** + * Returns the receiver's alpha value. + * + * @return the alpha value + * + * @exception DWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.4 + */ +public int getAlpha () { + checkWidget (); + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { + ubyte [1] pbAlpha; + if (OS.GetLayeredWindowAttributes (handle, null, pbAlpha.ptr, null)) { + return pbAlpha [0] & 0xFF; + } + } + return 0xFF; +} + override public Rectangle getBounds () { checkWidget (); static if (!OS.IsWinCE) { @@ -906,6 +949,25 @@ } /** + * Returns true if the receiver is currently + * in fullscreen state, and false otherwise. + *

    + * + * @return the fullscreen state + * + * @exception DWTException

      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.4 + */ +public bool getFullScreen () { + checkWidget(); + return fullScreen; +} + +/** * Returns the receiver's input method editor mode. This * will be the result of bitwise OR'ing together one or * more of the following constants defined in class @@ -951,6 +1013,11 @@ return new Point (rect.left, rect.top); } +public bool getMaximized () { + checkWidget (); + return !fullScreen && super.getMaximized (); +} + /** * Returns a point describing the minimum receiver's size. The * x coordinate of the result is the minimum width of the receiver. @@ -1003,6 +1070,7 @@ * */ public Region getRegion () { + /* This method is needed for the @since 3.0 Javadoc */ checkWidget (); return region; } @@ -1151,6 +1219,13 @@ if (!restoreFocus () && !traverseGroup (true)) setFocus (); } +public bool print (GC gc) { + checkWidget (); + if (gc is null) error (DWT.ERROR_NULL_ARGUMENT); + if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + return false; +} + override void register () { super.register (); if (toolTipHandle_ !is null) display.addControl (toolTipHandle_, this); @@ -1210,9 +1285,7 @@ if (hIMC !is null) OS.ImmDestroyContext (hIMC); } lastActive = null; - region = null; toolTitle = balloonTitle = null; - lockToolTipControl = null; } override void removeMenu (Menu menu) { @@ -1262,6 +1335,11 @@ return (result > 0) ? LRESULT.ONE : LRESULT.ZERO; } +bool sendKeyEvent (int type, int msg, int /*long*/ wParam, int /*long*/ lParam, Event event) { + if (!isEnabled () || !isActive ()) return false; + return super.sendKeyEvent (type, msg, wParam, lParam, event); +} + /** * If the receiver is visible, moves it to the top of the * drawing order for the display on which it was created @@ -1327,7 +1405,52 @@ } } +/** + * Sets the receiver's alpha value. + *

    + * This operation requires the operating system's advanced + * widgets subsystem which may not be available on some + * platforms. + *

    + * @param alpha the alpha value + * + * @exception DWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.4 + */ +public void setAlpha (int alpha) { + checkWidget (); + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (5, 1)) { + alpha &= 0xFF; + int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); + if (alpha is 0xFF) { + OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits & ~OS.WS_EX_LAYERED); + int flags = OS.RDW_ERASE | OS.RDW_INVALIDATE | OS.RDW_FRAME | OS.RDW_ALLCHILDREN; + OS.RedrawWindow (handle, null, null, flags); + } else { + OS.SetWindowLong (handle, OS.GWL_EXSTYLE, bits | OS.WS_EX_LAYERED); + OS.SetLayeredWindowAttributes (handle, 0, cast(byte)alpha, OS.LWA_ALPHA); + } + } +} + override void setBounds (int x, int y, int width, int height, int flags, bool defer) { + if (fullScreen) setFullScreen (false); + /* + * Bug in Windows. When a window has alpha and + * SetWindowPos() is called with SWP_DRAWFRAME, + * the contents of the window are copied rather + * than allowing the windows underneath to draw. + * This causes pixel corruption. The fix is to + * clear the SWP_DRAWFRAME bits. + */ + int bits = OS.GetWindowLong (handle, OS.GWL_EXSTYLE); + if ((bits & OS.WS_EX_LAYERED) !is 0) { + flags &= ~OS.SWP_DRAWFRAME; + } super.setBounds (x, y, width, height, flags, false); } @@ -1341,6 +1464,54 @@ } /** + * Sets the full screen state of the receiver. + * If the argument is true causes the receiver + * to switch to the full screen state, and if the argument is + * false and the receiver was previously switched + * into full screen state, causes the receiver to switch back + * to either the maximmized or normal states. + *

    + * Note: The result of intermixing calls to setFullScreen(true), + * setMaximized(true) and setMinimized(true) will + * vary by platform. Typically, the behavior will match the platform user's + * expectations, but not always. This should be avoided if possible. + *

    + * + * @param fullScreen the new fullscreen state + * + * @exception DWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.4 + */ +public void setFullScreen (bool fullScreen) { + checkWidget(); + if (this.fullScreen is fullScreen) return; + int stateFlags = fullScreen ? OS.SW_SHOWMAXIMIZED : OS.SW_RESTORE; + int styleFlags = OS.GetWindowLong (handle, OS.GWL_STYLE); + int mask = DWT.TITLE | DWT.CLOSE | DWT.MIN | DWT.MAX; + if ((style & mask) !is 0) { + if (fullScreen) { + styleFlags = styleFlags & ~OS.WS_CAPTION; + } else { + styleFlags = styleFlags | OS.WS_CAPTION; + } + } + if (fullScreen) wasMaximized = getMaximized (); + bool visible = isVisible (); + OS.SetWindowLong (handle, OS.GWL_STYLE, styleFlags); + if (wasMaximized) { + OS.ShowWindow (handle, OS.SW_HIDE); + stateFlags = OS.SW_SHOWMAXIMIZED; + } + if (visible) OS.ShowWindow (handle, stateFlags); + OS.UpdateWindow (handle); + this.fullScreen = fullScreen; +} + +/** * Sets the input method editor mode to the argument which * should be the result of bitwise OR'ing together one or more * of the following constants defined in class DWT: @@ -1359,7 +1530,7 @@ public void setImeInputMode (int mode) { checkWidget (); if (!OS.IsDBLocale) return; - bool imeOn = mode !is DWT.NONE && mode !is DWT.ROMAN; + bool imeOn = mode !is DWT.NONE; auto hIMC = OS.ImmGetContext (handle); OS.ImmSetOpenStatus (hIMC, imeOn); if (imeOn) { @@ -1376,7 +1547,7 @@ oldBits = OS.IME_CMODE_KATAKANA; } } - if ((mode & DWT.DBCS) !is 0) { + if ((mode & (DWT.DBCS | DWT.NATIVE)) !is 0) { newBits |= OS.IME_CMODE_FULLSHAPE; } else { oldBits |= OS.IME_CMODE_FULLSHAPE; @@ -1386,7 +1557,8 @@ } else { oldBits |= OS.IME_CMODE_ROMAN; } - lpfdwConversion |= newBits; lpfdwConversion &= ~oldBits; + lpfdwConversion |= newBits; + lpfdwConversion &= ~oldBits; OS.ImmSetConversionStatus (hIMC, lpfdwConversion, lpfdwSentence); } } @@ -1492,14 +1664,7 @@ public void setRegion (Region region) { checkWidget (); if ((style & DWT.NO_TRIM) is 0) return; - if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT); - HRGN hRegion; - if (region !is null) { - hRegion = OS.CreateRectRgn (0, 0, 0, 0); - OS.CombineRgn (hRegion, region.handle, hRegion, OS.RGN_OR); - } - OS.SetWindowRgn (handle, hRegion, true); - this.region = region; + super.setRegion (region); } void setToolTipText (HWND hwnd, String text) { @@ -1522,7 +1687,7 @@ } } -void setToolTipText (NMTTDISPINFO* lpnmtdi, byte [] buffer) { +void setToolTipText (NMTTDISPINFO* lpnmtdi, char [] buffer) { /* * Ensure that the current position of the mouse * is inside the client area of the shell. This @@ -1538,7 +1703,7 @@ lpnmtdi.lpszText = lpstrTip; } -void setToolTipText (NMTTDISPINFO* lpnmtdi, char [] buffer) { +void setToolTipText (NMTTDISPINFO* lpnmtdi, wchar [] buffer) { /* * Ensure that the current position of the mouse * is inside the client area of the shell. This @@ -1548,7 +1713,7 @@ if (!hasCursor ()) return; auto hHeap = OS.GetProcessHeap (); if (lpstrTip !is null) OS.HeapFree (hHeap, 0, lpstrTip); - TCHAR[] charz = StrToTCHARs( 0, buffer ); + TCHAR[] charz = buffer;//StrToTCHARs( 0, buffer ); int byteCount = charz.length * TCHAR.sizeof; lpstrTip = cast(TCHAR*)OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory (lpstrTip, charz.ptr, byteCount); @@ -1605,12 +1770,6 @@ override public void setVisible (bool visible) { checkWidget (); - if (drawCount !is 0) { - if (((state & HIDDEN) is 0) is visible) return; - } else { - if (visible is OS.IsWindowVisible (handle)) return; - } - /* * Feature in Windows. When ShowWindow() is called used to hide * a window, Windows attempts to give focus to the parent. If the @@ -1624,6 +1783,9 @@ if ((style & mask) !is 0) { if (visible) { display.setModalShell (this); + if ((style & (DWT.APPLICATION_MODAL | DWT.SYSTEM_MODAL)) !is 0) { + display.setModalDialog (null); + } Control control = display._getFocusControl (); if (control !is null && !control.isActive ()) { bringToTop (); @@ -1656,22 +1818,41 @@ if (!visible) fixActiveShell (); super.setVisible (visible); if (isDisposed ()) return; - if (showWithParent is visible) return; - showWithParent = visible; + if (showWithParent !is visible) { + showWithParent = visible; + if (visible) { + static if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, true); + } + } + + /* Make the splash screen appear in the task bar */ if (visible) { - static if (!OS.IsWinCE) OS.ShowOwnedPopups (handle, true); + if (parent !is null && (parent.state & FOREIGN_HANDLE) !is 0) { + auto hwndParent = parent.handle; + int style = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE); + if ((style & OS.WS_EX_TOOLWINDOW) !is 0) { + OS.SetWindowLong (hwndParent, OS.GWL_EXSTYLE, style & ~OS.WS_EX_TOOLWINDOW); + /* + * Bug in Windows. The window does not show in the task bar when + * WS_EX_TOOLWINDOW is removed after the window has already been shown. + * The fix is to hide and shown the shell. + */ + OS.ShowWindow (hwndParent, OS.SW_HIDE); + OS.ShowWindow (hwndParent, OS.SW_RESTORE); + } + } } } override void subclass () { super.subclass (); if (ToolTipProc !is null) { - int newProc = display.windowProc; + int /*long*/ newProc = display.windowProc; if (toolTipHandle_ !is null) { - OS.SetWindowLong (toolTipHandle_, OS.GWL_WNDPROC, newProc); + OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, newProc); } if (balloonTipHandle_ !is null) { - OS.SetWindowLong (balloonTipHandle_, OS.GWL_WNDPROC, newProc); + OS.SetWindowLongPtr (balloonTipHandle_, OS.GWLP_WNDPROC, newProc); } } } @@ -1698,10 +1879,10 @@ super.unsubclass (); if (ToolTipProc !is null) { if (toolTipHandle_ !is null) { - OS.SetWindowLong (toolTipHandle_, OS.GWL_WNDPROC, cast(int)ToolTipProc); + OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, cast(int)ToolTipProc); } if (toolTipHandle_ !is null) { - OS.SetWindowLong (toolTipHandle_, OS.GWL_WNDPROC, cast(int)ToolTipProc); + OS.SetWindowLongPtr (toolTipHandle_, OS.GWLP_WNDPROC, cast(int)ToolTipProc); } } } @@ -1780,7 +1961,7 @@ static if (OS.IsSP) return cast(int) DialogProc; if ((style & DWT.TOOL) !is 0) { int trim = DWT.TITLE | DWT.CLOSE | DWT.MIN | DWT.MAX | DWT.BORDER | DWT.RESIZE; - if ((style & trim) is 0) super.windowProc (); + if ((style & trim) is 0) return super.windowProc (); } return parent !is null ? cast(int) DialogProc : super.windowProc (); } @@ -1858,14 +2039,14 @@ * to adding a listener. */ if (hooks (DWT.HardKeyDown) || hooks (DWT.HardKeyUp)) { - int fActive = wParam & 0xFFFF; - int hwnd = fActive !is 0 ? handle : 0; + int fActive = OS.LOWORD (wParam); + int /*long*/ hwnd = fActive !is 0 ? handle : 0; for (int bVk=OS.VK_APP1; bVk<=OS.VK_APP6; bVk++) { OS.SHSetAppKeyWndAssoc (cast(byte) bVk, hwnd); } } /* Restore SIP state when window is activated */ - if ((wParam & 0xFFFF) !is 0) { + if (OS.LOWORD (wParam) !is 0) { OS.SHSipPreference (handle, psai.fSipUp is 0 ? OS.SIP_DOWN : OS.SIP_UP); } } @@ -1873,24 +2054,20 @@ /* * Bug in Windows XP. When a Shell is deactivated, the * IME composition window does not go away. This causes - * repaint issues. The fix is to close the IME to cause - * the composition string to be committed. - * - * Note. The IME needs to be reopened in order to preserve - * the input method status. + * repaint issues. The fix is to commit the composition + * string. */ if (OS.WIN32_VERSION >= OS.VERSION (5, 1)) { - if ((wParam & 0xFFFF) is 0 && OS.IsDBLocale && hIMC !is null) { - if (OS.ImmGetOpenStatus(hIMC)) { - OS.ImmSetOpenStatus (hIMC, false); - OS.ImmSetOpenStatus (hIMC, true); + if (OS.LOWORD (wParam) is 0 && OS.IsDBLocale && hIMC !is null) { + if (OS.ImmGetOpenStatus (hIMC)) { + OS.ImmNotifyIME (hIMC, OS.NI_COMPOSITIONSTR, OS.CPS_COMPLETE, 0); } } } /* Process WM_ACTIVATE */ LRESULT result = super.WM_ACTIVATE (wParam, lParam); - if ((wParam & 0xFFFF) is 0) { + if (OS.LOWORD (wParam) is 0) { if (lParam is 0 || (cast(HANDLE)lParam !is toolTipHandle_ && cast(HANDLE)lParam !is balloonTipHandle_)) { ToolTip tip = getCurrentToolTip (); if (tip !is null) tip.setVisible (false); @@ -1906,7 +2083,7 @@ * been pressed. lParam is either 0 (PocketPC 2002) or the handle * to the Shell (PocketPC). */ - int loWord = wParam & 0xFFFF; + int loWord = OS.LOWORD (wParam); if (loWord is OS.IDOK && (lParam is 0 || lParam is handle)) { OS.PostMessage (handle, OS.WM_CLOSE, 0, 0); return LRESULT.ZERO; @@ -1929,7 +2106,7 @@ if (lParam is hwndCB) { return super.WM_COMMAND (wParam, 0); } else { - int hwndChild = OS.GetWindow (hwndCB, OS.GW_CHILD); + int /*long*/ hwndChild = OS.GetWindow (hwndCB, OS.GW_CHILD); if (lParam is hwndChild) return super.WM_COMMAND (wParam, 0); } } @@ -1975,10 +2152,8 @@ override LRESULT WM_ENTERIDLE (int wParam, int lParam) { LRESULT result = super.WM_ENTERIDLE (wParam, lParam); if (result !is null) return result; - static if (OS.IsWinCE) { - if (display.runMessages) { - if (display.runAsyncMessages (true)) display.wakeThread (); - } + if (display.runMessages) { + if (display.runAsyncMessages (false)) display.wakeThread (); } return result; } @@ -2006,7 +2181,7 @@ * and stop the normal shell activation but allow the mouse * down to be delivered. */ - int hittest = cast(short) (lParam & 0xFFFF); + int hittest = cast(short) OS.LOWORD (lParam); switch (hittest) { case OS.HTERROR: case OS.HTTRANSPARENT: @@ -2049,8 +2224,7 @@ POINT pt; if (!OS.GetCursorPos (&pt)) { int pos = OS.GetMessagePos (); - pt.x = cast(short) (pos & 0xFFFF); - pt.y = cast(short) (pos >> 16); + OS.POINTSTOPOINT (pt, pos); } auto hwnd = OS.WindowFromPoint (pt); if (hwnd is null) return null; @@ -2073,8 +2247,9 @@ } } + int /*long*/ code = callWindowProc (handle, OS.WM_MOUSEACTIVATE, wParam, lParam); setActiveControl (control); - return null; + return new LRESULT (code); } override LRESULT WM_MOVE (int wParam, int lParam) { @@ -2085,32 +2260,16 @@ return result; } -override LRESULT WM_NCACTIVATE (int wParam, int lParam) { - Display display = this.display; - LRESULT result = super.WM_NCACTIVATE (wParam, lParam); - if (display.isXMouseActive ()) { - if (lockToolTipControl !is null) { - if (OS.GetAsyncKeyState (OS.VK_LBUTTON) < 0) return result; - if (OS.GetAsyncKeyState (OS.VK_MBUTTON) < 0) return result; - if (OS.GetAsyncKeyState (OS.VK_RBUTTON) < 0) return result; - if (OS.GetAsyncKeyState (OS.VK_XBUTTON1) < 0) return result; - if (OS.GetAsyncKeyState (OS.VK_XBUTTON2) < 0) return result; - return LRESULT.ZERO; - } - } - return result; -} - override LRESULT WM_NCHITTEST (int wParam, int lParam) { if (!OS.IsWindowEnabled (handle)) return null; if (!isEnabled () || !isActive ()) { if (!Display.TrimEnabled) return new LRESULT (OS.HTNOWHERE); - int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); + int /*long*/ hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); if (hittest is OS.HTCLIENT || hittest is OS.HTMENU) hittest = OS.HTBORDER; return new LRESULT (hittest); } if (menuBar !is null && !menuBar.getEnabled ()) { - int hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); + int /*long*/ hittest = callWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); if (hittest is OS.HTMENU) hittest = OS.HTBORDER; return new LRESULT (hittest); } @@ -2133,7 +2292,7 @@ bool fixActive = OS.IsWin95 && display.lastHittest is OS.HTCAPTION; if (fixActive) hwndActive = OS.SetActiveWindow (handle); display.lockActiveWindow = true; - int code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_NCLBUTTONDOWN, wParam, lParam); display.lockActiveWindow = false; if (fixActive) OS.SetActiveWindow (hwndActive); Control focusControl = display.lastHittestControl; @@ -2168,7 +2327,7 @@ * fix is to detect this case and bring the shell * forward. */ - int msg = cast(short) (lParam >> 16); + int msg = OS.HIWORD (lParam); if (msg is OS.WM_LBUTTONDOWN) { if (!Display.TrimEnabled) { Shell modalShell = display.getModalShell (); @@ -2203,15 +2362,14 @@ * with HTERROR to set the cursor but only when the * mouse is in the client area of the shell. */ - int hitTest = cast(short) (lParam & 0xFFFF); + int hitTest = cast(short) OS.LOWORD (lParam); if (hitTest is OS.HTERROR) { if (!getEnabled ()) { Control control = display.getControl (cast(HANDLE)wParam); if (control is this && cursor !is null) { POINT pt; int pos = OS.GetMessagePos (); - pt.x = cast(short) (pos & 0xFFFF); - pt.y = cast(short) (pos >> 16); + OS.POINTSTOPOINT (pt, pos); OS.ScreenToClient (handle, &pt); RECT rect; OS.GetClientRect (handle, &rect); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Slider.d --- a/dwt/widgets/Slider.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Slider.d Sat May 17 17:34:28 2008 +0200 @@ -669,7 +669,7 @@ case OS.VK_LEFT: case OS.VK_RIGHT: { int key = wParam is OS.VK_LEFT ? OS.VK_RIGHT : OS.VK_LEFT; - int code = callWindowProc (handle, OS.WM_KEYDOWN, key, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, key, lParam); return new LRESULT (code); } default: @@ -752,7 +752,7 @@ override LRESULT wmScrollChild (int wParam, int lParam) { /* Do nothing when scrolling is ending */ - int code = wParam & 0xFFFF; + int code = OS.LOWORD (wParam); if (code is OS.SB_ENDSCROLL) return null; /* Move the thumb */ diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Spinner.d --- a/dwt/widgets/Spinner.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Spinner.d Sat May 17 17:34:28 2008 +0200 @@ -32,6 +32,7 @@ import tango.text.convert.Integer : toString; static import tango.text.Text; alias tango.text.Text.Text!(char) StringBuffer; +import tango.util.Convert; /** * Instances of this class are selectable user interface @@ -86,7 +87,22 @@ static_this_completed = true; } } + /** + * the operating system limit for the number of characters + * that the text field in an instance of this class can hold + * + * @since 3.4 + */ + public static int LIMIT; + /* + * These values can be different on different platforms. + * Therefore they are not initialized in the declaration + * to stop the compiler from inlining. + */ + static this() { + LIMIT = OS.IsWinNT ? 0x7FFFFFFF : 0x7FFF; + } /** * Constructs a new instance of this class given its parent @@ -173,7 +189,7 @@ hInstance, null); if (hwndText is null) error (DWT.ERROR_NO_HANDLES); - OS.SetWindowLong (hwndText, OS.GWL_ID, cast(int) hwndText); + OS.SetWindowLongPtr (hwndText, OS.GWLP_ID, cast(LONG_PTR)hwndText); int upDownStyle = OS.WS_CHILD | OS.WS_VISIBLE | OS.UDS_AUTOBUDDY; if ((style & DWT.WRAP) !is 0) upDownStyle |= OS.UDS_WRAP; if ((style & DWT.BORDER) !is 0) { @@ -196,7 +212,7 @@ if (hwndUpDown is null) error (DWT.ERROR_NO_HANDLES); int flags = OS.SWP_NOSIZE | OS.SWP_NOMOVE | OS.SWP_NOACTIVATE; SetWindowPos (hwndText, hwndUpDown, 0, 0, 0, 0, flags); - OS.SetWindowLong (hwndUpDown, OS.GWL_ID, cast(int) hwndUpDown); + OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_ID, cast(LONG_PTR)hwndUpDown); if (OS.IsDBLocale) { auto hIMC = OS.ImmGetContext (handle); OS.ImmAssociateContext (hwndText, hIMC); @@ -365,9 +381,9 @@ * the single-line text widget in an editable combo * box. */ - int margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0); - x -= margins & 0xFFFF; - width += (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF); + int /*long*/ margins = OS.SendMessage (hwndText, OS.EM_GETMARGINS, 0, 0); + x -= OS.LOWORD (margins); + width += OS.LOWORD (margins) + OS.HIWORD (margins); if ((style & DWT.BORDER) !is 0) { x -= 1; y -= 1; @@ -538,13 +554,13 @@ public int getSelection () { checkWidget (); static if (OS.IsWinCE) { - return OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF; + return OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0)); } else { return OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0); } } -int getSelectionText () { +int getSelectionText (bool [] parseFail) { int length_ = OS.GetWindowTextLength (hwndText); TCHAR[] buffer = NewTCHARs (getCodePage (), length_ + 1); OS.GetWindowText (hwndText, buffer.ptr, length_ + 1); @@ -555,7 +571,8 @@ String decimalSeparator = getDecimalSeparator (); int index = string.indexOf (decimalSeparator); if (index !is -1) { - String wholePart = string.substring (0, index); + int startIndex = string.startsWith ("+") || string.startsWith ("-") ? 1 : 0; + String wholePart = startIndex !is index ? string.substring (startIndex, index) : "0"; String decimalPart = string.substring (index + 1); if (decimalPart.length > digits) { decimalPart = decimalPart.substring (0, digits); @@ -569,8 +586,10 @@ int decimalValue = Integer.parseInt (decimalPart); for (int i = 0; i < digits; i++) wholeValue *= 10; value = wholeValue + decimalValue; + if (string.startsWith ("-")) value = -value; } else { value = Integer.parseInt (string); + for (int i = 0; i < digits; i++) value *= 10; } } else { value = Integer.parseInt (string); @@ -580,9 +599,55 @@ if (min <= value && value <= max) return value; } catch (NumberFormatException e) { } + parseFail [0] = true; return -1; } +/** + * Returns a string containing a copy of the contents of the + * receiver's text field, or an empty string if there are no + * contents. + * + * @return the receiver's text + * + * @exception DWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @since 3.4 + */ +public String getText () { + checkWidget (); + int length_ = OS.GetWindowTextLength (hwndText); + if (length_ is 0) return ""; + TCHAR[] buffer = NewTCHARs (getCodePage (), length_ + 1); + OS.GetWindowText (hwndText, buffer.ptr, length_ + 1); + return TCHARsToStr( buffer[0 .. length_] ); +} + +/** + * Returns the maximum number of characters that the receiver's + * text field is capable of holding. If this has not been changed + * by setTextLimit(), it will be the constant + * Spinner.LIMIT. + * + * @return the text limit + * + * @exception DWTException
      + *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • + *
    • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
    • + *
    + * + * @see #LIMIT + * + * @since 3.4 + */ +public int getTextLimit () { + checkWidget (); + return OS.SendMessage (hwndText, OS.EM_GETLIMITTEXT, 0, 0) & 0x7FFFFFFF; +} + int mbcsToWcsPos (int mbcsPos) { if (mbcsPos <= 0) return 0; if (OS.IsUnicode) return mbcsPos; @@ -817,7 +882,7 @@ this.digits = value; int pos; static if (OS.IsWinCE) { - pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF; + pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0)); } else { pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0); } @@ -876,13 +941,12 @@ */ public void setMaximum (int value) { checkWidget (); - if (value < 0) return; int min; OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, null); if (value <= min) return; int pos; static if (OS.IsWinCE) { - pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF; + pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0)); } else { pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0); } @@ -892,11 +956,11 @@ /** * Sets the minimum value that the receiver will allow. This new - * value will be ignored if it is negative or is not less than the receiver's + * value will be ignored if it is not less than the receiver's * current maximum value. If the new minimum is applied then the receiver's * selection value will be adjusted if necessary to fall within its new range. * - * @param value the new minimum, which must be nonnegative and less than the current maximum + * @param value the new minimum, which must be less than the current maximum * * @exception DWTException
      *
    • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
    • @@ -905,13 +969,12 @@ */ public void setMinimum (int value) { checkWidget (); - if (value < 0) return; int max; OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, null, &max); if (value >= max) return; int pos; static if (OS.IsWinCE) { - pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF; + pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0)); } else { pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0); } @@ -963,11 +1026,15 @@ OS.SendMessage (hwndUpDown , OS.IsWinCE ? OS.UDM_SETPOS : OS.UDM_SETPOS32, 0, value); } if (setText) { - String string = .toString( value ); - if (digits > 0) { + String string; + if (digits is 0) { + string = .toString (value); + } else { + string = to!(String)(Math.abs (value)); String decimalSeparator = getDecimalSeparator (); int index = string.length - digits; StringBuffer buffer = new StringBuffer (); + if (value < 0) buffer.append ("-"); if (index > 0) { buffer.append (string.substring (0, index)); buffer.append (decimalSeparator); @@ -987,10 +1054,42 @@ } TCHAR* buffer = StrToTCHARz (getCodePage (), string); OS.SetWindowText (hwndText, buffer); + OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1); + if (!OS.IsWinCE) { + OS.NotifyWinEvent (OS.EVENT_OBJECT_FOCUS, hwndText, OS.OBJID_CLIENT, 0); + } } if (notify) postEvent (DWT.Selection); } +/** + * Sets the maximum number of characters that the receiver's + * text field is capable of holding to be the argument. + *

      + * To reset this value to the default, use setTextLimit(Spinner.LIMIT). + * Specifying a limit value larger than Spinner.LIMIT sets the + * receiver's limit to Spinner.LIMIT. + *

      + * @param limit new text limit + * + * @exception IllegalArgumentException
        + *
      • ERROR_CANNOT_BE_ZERO - if the limit is zero
      • + *
      + * @exception DWTException
        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @see #LIMIT + * + * @since 3.4 + */ +public void setTextLimit (int limit) { + checkWidget (); + if (limit is 0) error (DWT.ERROR_CANNOT_BE_ZERO); + OS.SendMessage (hwndText, OS.EM_SETLIMITTEXT, limit, 0); +} + override void setToolTipText (Shell shell, String string) { shell.setToolTipText (hwndText, string); shell.setToolTipText (hwndUpDown, string); @@ -1021,7 +1120,6 @@ */ public void setValues (int selection, int minimum, int maximum, int digits, int increment, int pageIncrement) { checkWidget (); - if (minimum < 0) return; if (maximum <= minimum) return; if (digits < 0) return; if (increment < 1) return; @@ -1036,15 +1134,15 @@ override void subclass () { super.subclass (); - int newProc = display.windowProc; - OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, newProc); - OS.SetWindowLong (hwndUpDown, OS.GWL_WNDPROC, newProc); + int /*long*/ newProc = display.windowProc; + OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, newProc); + OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_WNDPROC, newProc); } override void unsubclass () { super.unsubclass (); - OS.SetWindowLong (hwndText, OS.GWL_WNDPROC, cast(int) EditProc); - OS.SetWindowLong (hwndUpDown, OS.GWL_WNDPROC, cast(int) UpDownProc); + OS.SetWindowLongPtr (hwndText, OS.GWLP_WNDPROC, cast(LONG_PTR)EditProc); + OS.SetWindowLongPtr (hwndUpDown, OS.GWLP_WNDPROC, cast(LONG_PTR)UpDownProc); } String verifyText (String string, int start, int end, Event keyEvent) { @@ -1066,6 +1164,11 @@ } index = 0; } + if (string.length > 0) { + int min; + OS.SendMessage (hwndUpDown , OS.UDM_GETRANGE32, &min, null); + if (min < 0 && string.charAt (0) is '-') index++; + } while (index < string.length ) { if (!CharacterIsDigit (string.charAt (index))) break; index++; @@ -1157,6 +1260,7 @@ override LRESULT WM_SETFOCUS (int wParam, int lParam) { OS.SetFocus (hwndText); + OS.SendMessage (hwndText, OS.EM_SETSEL, 0, -1); return null; } @@ -1170,7 +1274,7 @@ override LRESULT WM_SIZE (int wParam, int lParam) { LRESULT result = super.WM_SIZE (wParam, lParam); if (isDisposed ()) return result; - int width = lParam & 0xFFFF, height = lParam >> 16; + int width = OS.LOWORD (lParam), height = OS.HIWORD (lParam); int upDownWidth = OS.GetSystemMetrics (OS.SM_CXVSCROLL); int textWidth = width - upDownWidth; int border = OS.GetSystemMetrics (OS.SM_CXEDGE); @@ -1269,15 +1373,16 @@ } override LRESULT wmCommandChild (int wParam, int lParam) { - int code = wParam >> 16; + int code = OS.HIWORD (wParam); switch (code) { case OS.EN_CHANGE: if (ignoreModify) break; - int value = getSelectionText (); - if (value !is -1) { + bool [] parseFail = new bool [1]; + int value = getSelectionText (parseFail); + if (!parseFail [0]) { int pos; static if (OS.IsWinCE) { - pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF; + pos = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0)); } else { pos = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0); } @@ -1307,10 +1412,11 @@ default: } if (delta !is 0) { - int value = getSelectionText (); - if (value !is -1) { + bool [1] parseFail; + int value = getSelectionText (parseFail); + if (parseFail [0]) { static if (OS.IsWinCE) { - value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF; + value = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0)); } else { value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0); } @@ -1337,10 +1443,11 @@ } override LRESULT wmKillFocus (HWND hwnd, int wParam, int lParam) { - int value = getSelectionText (); - if (value is -1) { + bool [1] parseFail; + int value = getSelectionText (parseFail); + if (parseFail [0]) { static if (OS.IsWinCE) { - value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0) & 0xFFFF; + value = OS.LOWORD (OS.SendMessage (hwndUpDown, OS.UDM_GETPOS, 0, 0)); } else { value = OS.SendMessage (hwndUpDown, OS.UDM_GETPOS32, 0, 0); } @@ -1380,7 +1487,7 @@ } override LRESULT wmScrollChild (int wParam, int lParam) { - int code = wParam & 0xFFFF; + int code = OS.LOWORD (wParam); switch (code) { case OS.SB_THUMBPOSITION: postEvent (DWT.Selection); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Synchronizer.d --- a/dwt/widgets/Synchronizer.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Synchronizer.d Sat May 17 17:34:28 2008 +0200 @@ -20,6 +20,7 @@ import dwt.DWT; import tango.core.Thread; +import dwt.graphics.Device; import tango.core.Exception; /** @@ -45,6 +46,8 @@ RunnableLock [] messages; Object messageLock; Thread syncThread; + static final int GROW_SIZE = 4; + static final int MESSAGE_LIMIT = 64; //TEMPORARY CODE static final bool IS_CARBON = false;//"carbon".equals (DWT.getPlatform ()); @@ -62,9 +65,9 @@ void addLast (RunnableLock lock) { bool wake = false; synchronized (messageLock) { - if (messages is null) messages = new RunnableLock [4]; + if (messages is null) messages = new RunnableLock [GROW_SIZE]; if (messageCount is messages.length) { - RunnableLock[] newMessages = new RunnableLock [messageCount + 4]; + RunnableLock[] newMessages = new RunnableLock [messageCount + GROW_SIZE]; System.arraycopy (messages, 0, newMessages, 0, messageCount); messages = newMessages; } @@ -116,7 +119,7 @@ System.arraycopy (messages, 1, messages, 0, --messageCount); messages [messageCount] = null; if (messageCount is 0) { - if (messages.length > 64) messages = null; + if (messages.length > MESSAGE_LIMIT) messages = null; } return lock; } @@ -163,21 +166,27 @@ * @see #asyncExec */ public void syncExec (Runnable runnable) { - if (display.isValidThread ()) { + RunnableLock lock = null; + synchronized (Device.classinfo) { + if (display is null || display.isDisposed ()) DWT.error (DWT.ERROR_DEVICE_DISPOSED); + if (!display.isValidThread ()) { + if (runnable is null) { + display.wake (); + return; + } + lock = new RunnableLock (runnable); + /* + * Only remember the syncThread for syncExec. + */ + lock.thread = Thread.getThis(); + addLast (lock); + } + } + if (lock is null) { if (runnable !is null) runnable.run (); return; } - if (runnable is null) { - display.wake (); - return; - } - RunnableLock lock = new RunnableLock (runnable); - /* - * Only remember the syncThread for syncExec. - */ - lock.thread = Thread.getThis(); synchronized (lock) { - addLast (lock); bool interrupted = false; while (!lock.done ()) { try { diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/TabFolder.d --- a/dwt/widgets/TabFolder.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/TabFolder.d Sat May 17 17:34:28 2008 +0200 @@ -376,6 +376,35 @@ } /** + * Returns the tab item at the given point in the receiver + * or null if no such item exists. The point is in the + * coordinate system of the receiver. + * + * @param point the point used to locate the item + * @return the tab item at the given point, or null if the point is not in a tab item + * + * @exception IllegalArgumentException
        + *
      • ERROR_NULL_ARGUMENT - if the point is null
      • + *
      + * @exception DWTException
        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @since 3.4 + */ +public TabItem getItem (Point point) { + checkWidget (); + if (point is null) error (DWT.ERROR_NULL_ARGUMENT); + TCHITTESTINFO pinfo; + pinfo.pt.x = point.x; + pinfo.pt.y = point.y; + int index = OS.SendMessage (handle, OS.TCM_HITTEST, 0, &pinfo); + if (index is -1) return null; + return items [index]; +} + +/** * Returns the number of items contained in the receiver. * * @return the number of items @@ -732,6 +761,18 @@ int index = hdr.hdr.idFrom; auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TCM_GETTOOLTIPS, 0, 0); if (hwndToolTip is hdr.hdr.hwndFrom) { + /* + * Bug in Windows. For some reason the reading order + * in NMTTDISPINFO is sometimes set incorrectly. The + * reading order seems to change every time the mouse + * enters the control from the top edge. The fix is + * to explicitly set TTF_RTLREADING. + */ + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + hdr.uFlags |= OS.TTF_RTLREADING; + } else { + hdr.uFlags &= ~OS.TTF_RTLREADING; + } if (toolTipText_ !is null) return ""; if (0 <= index && index < items.length) { TabItem item = items [index]; @@ -835,7 +876,7 @@ * default window proc that returns HTCLIENT when * the mouse is in the client area. */ - int hittest = OS.DefWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); + int /*long*/ hittest = OS.DefWindowProc (handle, OS.WM_NCHITTEST, wParam, lParam); return new LRESULT (hittest); } @@ -878,10 +919,10 @@ */ if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return result; if ((style & DWT.RIGHT_TO_LEFT) !is 0) { - int code = wParam & 0xFFFF; + int code = OS.LOWORD (wParam); switch (code) { case OS.WM_CREATE: { - int id = (wParam >> 16); + int id = OS.HIWORD (wParam); HWND hwnd = cast(HWND) lParam; if (id is ID_UPDOWN) { auto bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/TabItem.d --- a/dwt/widgets/TabItem.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/TabItem.d Sat May 17 17:34:28 2008 +0200 @@ -15,6 +15,7 @@ import dwt.DWT; import dwt.DWTException; import dwt.graphics.Image; +import dwt.graphics.Rectangle; import dwt.internal.win32.OS; import dwt.widgets.Item; @@ -177,6 +178,28 @@ } /** + * Returns a rectangle describing the receiver's size and location + * relative to its parent. + * + * @return the receiver's bounding rectangle + * + * @exception DWTException
        + *
      • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
      • + *
      • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
      • + *
      + * + * @since 3.4 + */ +public Rectangle getBounds() { + checkWidget(); + int index = parent.indexOf(this); + if (index is -1) return new Rectangle (0, 0, 0, 0); + RECT itemRect; + OS.SendMessage (parent.handle, OS.TCM_GETITEMRECT, index, &itemRect); + return new Rectangle(itemRect.left, itemRect.top, itemRect.right - itemRect.left, itemRect.bottom - itemRect.top); +} + +/** * Returns the receiver's parent, which must be a TabFolder. * * @return the receiver's parent diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Table.d --- a/dwt/widgets/Table.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Table.d Sat May 17 17:34:28 2008 +0200 @@ -33,6 +33,7 @@ import dwt.widgets.Event; import dwt.widgets.Control; import dwt.widgets.Display; +import dwt.widgets.Shell; import dwt.dwthelper.utils; @@ -66,12 +67,13 @@ * *

      * Note that although this class is a subclass of Composite, - * it does not make sense to add Control children to it, - * or set a layout on it. + * it does not normally make sense to add Control children to + * it, or set a layout on it, unless implementing something like a cell + * editor. *

      *

      *
      Styles:
      - *
      SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION, VIRTUAL
      + *
      SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION, VIRTUAL, NO_SCROLL
      *
      Events:
      *
      Selection, DefaultSelection, SetData, MeasureItem, EraseItem, PaintItem
      *
      @@ -96,10 +98,11 @@ ImageList imageList, headerImageList; TableItem currentItem; TableColumn sortColumn; + RECT* focusRect; + HWND headerToolTipHandle; bool ignoreCustomDraw, ignoreDrawForeground, ignoreDrawBackground, ignoreDrawFocus, ignoreDrawSelection, ignoreDrawHot; bool customDraw, dragStarted, explorerTheme, firstColumnImage, fixScrollWidth, tipRequested, wasSelected, wasResized; - bool ignoreActivate, ignoreSelect, ignoreShrink, ignoreResize, ignoreColumnMove, ignoreColumnResize; - HWND headerToolTipHandle; + bool ignoreActivate, ignoreSelect, ignoreShrink, ignoreResize, ignoreColumnMove, ignoreColumnResize, fullRowSelect; int itemHeight, lastIndexOf, lastWidth, sortDirection, resizeCount, selectionForeground, hotIndex; static /*final*/ WNDPROC HeaderProc; static const int INSET = 4; @@ -109,6 +112,8 @@ static const int HEADER_EXTRA = 3; static const int VISTA_EXTRA = 2; static const int EXPLORER_EXTRA = 2; + static final int H_SCROLL_LIMIT = 32; + static final int V_SCROLL_LIMIT = 16; static const bool EXPLORER_THEME = true; private static /+const+/ WNDPROC TableProc; static const TCHAR[] TableClass = OS.WC_LISTVIEW; @@ -159,6 +164,7 @@ * @see DWT#FULL_SELECTION * @see DWT#HIDE_SELECTION * @see DWT#VIRTUAL + * @see DWT#NO_SCROLL * @see Widget#checkSubclass * @see Widget#getStyle */ @@ -176,8 +182,7 @@ setCustomDraw (true); setBackgroundTransparent (true); if (OS.COMCTL32_MAJOR < 6) style |= DWT.DOUBLE_BUFFERED; - //TODO - LVS_EX_LABELTIP causes white rectangles (turn it off) - OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_LABELTIP, 0); + if (OS.IsWinCE) OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_LABELTIP, 0); break; default: } @@ -263,7 +268,16 @@ /* Resize messages */ case OS.WM_WINDOWPOSCHANGED: redraw = findImageControl () !is null && drawCount is 0 && OS.IsWindowVisible (handle); - if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); + if (redraw) { + /* + * Feature in Windows. When LVM_SETBKCOLOR is used with CLR_NONE + * to make the background of the table transparent, drawing becomes + * slow. The fix is to temporarily clear CLR_NONE when redraw is + * turned off. + */ + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); + OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, 0xFFFFFF); + } //FALL THROUGH /* Mouse messages */ @@ -298,7 +312,66 @@ bool oldSelected = wasSelected; if (checkSelection) wasSelected = false; if (checkActivate) ignoreActivate = true; - int code = OS.CallWindowProc (TableProc, hwnd, msg, wParam, lParam); + + /* + * Bug in Windows. For some reason, when the WS_EX_COMPOSITED + * style is set in a parent of a table and the header is visible, + * Windows issues an endless stream of WM_PAINT messages. The + * fix is to call BeginPaint() and EndPaint() outside of WM_PAINT + * and pass the paint HDC in to the window proc. + */ + bool fixPaint = false; + if (msg is OS.WM_PAINT) { + int bits0 = OS.GetWindowLong (handle, OS.GWL_STYLE); + if ((bits0 & OS.LVS_NOCOLUMNHEADER) is 0) { + HWND hwndParent = OS.GetParent (handle), hwndOwner = null; + while (hwndParent !is null) { + int bits1 = OS.GetWindowLong (hwndParent, OS.GWL_EXSTYLE); + if ((bits1 & OS.WS_EX_COMPOSITED) !is 0) { + fixPaint = true; + break; + } + hwndOwner = OS.GetWindow (hwndParent, OS.GW_OWNER); + if (hwndOwner !is null) break; + hwndParent = OS.GetParent (hwndParent); + } + } + } + + /* Remove the scroll bars that Windows keeps automatically adding */ + bool fixScroll = false; + if ((style & DWT.H_SCROLL) is 0 || (style & DWT.V_SCROLL) is 0) { + switch (msg) { + case OS.WM_PAINT: + case OS.WM_NCPAINT: + case OS.WM_WINDOWPOSCHANGING: { + int bits = OS.GetWindowLong (hwnd, OS.GWL_STYLE); + if ((style & DWT.H_SCROLL) is 0 && (bits & OS.WS_HSCROLL) !is 0) { + fixScroll = true; + bits &= ~OS.WS_HSCROLL; + } + if ((style & DWT.V_SCROLL) is 0 && (bits & OS.WS_VSCROLL) !is 0) { + fixScroll = true; + bits &= ~OS.WS_VSCROLL; + } + if (fixScroll) OS.SetWindowLong (handle, OS.GWL_STYLE, bits); + } + } + } + int /*long*/ code = 0; + if (fixPaint) { + PAINTSTRUCT ps; + auto hDC = OS.BeginPaint (hwnd, &ps); + code = TableProc( hwnd, OS.WM_PAINT, cast(int)hDC, lParam); + OS.EndPaint (hwnd, &ps); + } else { + code = TableProc( hwnd, msg, wParam, lParam); + } + if (fixScroll) { + int flags = OS.RDW_FRAME | OS.RDW_INVALIDATE; + OS.RedrawWindow (handle, null, null, flags); + } + if (checkActivate) ignoreActivate = false; if (checkSelection) { if (wasSelected || forceSelect) { @@ -328,6 +401,7 @@ /* Resize messages */ case OS.WM_WINDOWPOSCHANGED: if (redraw) { + OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, OS.CLR_NONE); OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); OS.InvalidateRect (handle, null, true); auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); @@ -370,13 +444,17 @@ static int checkStyle (int style) { /* - * Feature in Windows. It is not possible to create - * a table that does not have scroll bars. Therefore, - * no matter what style bits are specified, set the - * H_SCROLL and V_SCROLL bits so that the DWT style - * will match the widget that Windows creates. + * Feature in Windows. Even when WS_HSCROLL or + * WS_VSCROLL is not specified, Windows creates + * trees and tables with scroll bars. The fix + * is to set H_SCROLL and V_SCROLL. + * + * NOTE: This code appears on all platforms so that + * applications have consistent scroll bar behavior. */ - style |= DWT.H_SCROLL | DWT.V_SCROLL; + if ((style & DWT.NO_SCROLL) is 0) { + style |= DWT.H_SCROLL | DWT.V_SCROLL; + } return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0); } @@ -497,6 +575,13 @@ int dwExStyle = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) is 0) { int bits = OS.LVS_EX_FULLROWSELECT; + /* + * Feature in Windows. When LVM_SETEXTENDEDLISTVIEWSTYLE is + * used to set or clear the extended style bits and the table + * has a tooltip, the tooltip is hidden. The fix is to clear + * the tooltip before setting the bits and then reset it. + */ + int /*long*/ hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, 0, 0); static if (OS.IsWinCE) { RECT rect; bool damaged = cast(bool) OS.GetUpdateRect (handle, &rect, true); @@ -511,6 +596,12 @@ if (result !is OS.NULLREGION) OS.InvalidateRgn (handle, rgn, true); OS.DeleteObject (rgn); } + /* + * Bug in Windows. Despite the documentation, LVM_SETTOOLTIPS + * uses WPARAM instead of LPARAM for the new tooltip The fix + * is to put the tooltip in both parameters. + */ + hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, hwndToolTip, hwndToolTip); } } } @@ -536,6 +627,13 @@ int dwExStyle = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); if ((dwExStyle & OS.LVS_EX_FULLROWSELECT) !is 0) { int bits = OS.LVS_EX_FULLROWSELECT; + /* + * Feature in Windows. When LVM_SETEXTENDEDLISTVIEWSTYLE is + * used to set or clear the extended style bits and the table + * has a tooltip, the tooltip is hidden. The fix is to clear + * the tooltip before setting the bits and then reset it. + */ + auto hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, 0, 0); static if (OS.IsWinCE) { RECT rect; bool damaged = cast(bool) OS.GetUpdateRect (handle, &rect, true); @@ -550,6 +648,12 @@ if (result !is OS.NULLREGION) OS.InvalidateRgn (handle, rgn, true); OS.DeleteObject (rgn); } + /* + * Bug in Windows. Despite the documentation, LVM_SETTOOLTIPS + * uses WPARAM instead of LPARAM for the new tooltip The fix + * is to put the tooltip in both parameters. + */ + hwndToolTip = OS.SendMessage (handle, OS.LVM_SETTOOLTIPS, hwndToolTip, hwndToolTip); } } } @@ -653,6 +757,12 @@ sendPaintItemEvent (item, nmcd); //widget could be disposed at this point } + if (!ignoreDrawFocus && focusRect !is null) { + OS.SetTextColor (nmcd.nmcd.hdc, 0); + OS.SetBkColor (nmcd.nmcd.hdc, 0xFFFFFF); + OS.DrawFocusRect (nmcd.nmcd.hdc, focusRect); + focusRect = null; + } } return null; } @@ -672,8 +782,7 @@ */ TableItem item = _getItem (nmcd.nmcd.dwItemSpec); if (item is null) return null; - HFONT hFont = item.cellFont !is null ? item.cellFont [nmcd.iSubItem] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = item.font; + HFONT hFont = item.fontHandle (nmcd.iSubItem); if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); if (ignoreCustomDraw || (nmcd.nmcd.rc.left is nmcd.nmcd.rc.right)) { return new LRESULT (hFont is cast(HFONT)-1 ? OS.CDRF_DODEFAULT : OS.CDRF_NEWFONT); @@ -682,12 +791,13 @@ selectionForeground = -1; ignoreDrawForeground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawBackground = false; if (OS.IsWindowVisible (handle)) { + Event measureEvent = null; if (hooks (DWT.MeasureItem)) { - sendMeasureItemEvent (item, nmcd.nmcd.dwItemSpec, nmcd.iSubItem, nmcd.nmcd.hdc); + measureEvent = sendMeasureItemEvent (item, nmcd.nmcd.dwItemSpec, nmcd.iSubItem, nmcd.nmcd.hdc); if (isDisposed () || item.isDisposed ()) return null; } if (hooks (DWT.EraseItem)) { - sendEraseItemEvent (item, nmcd, lParam); + sendEraseItemEvent (item, nmcd, lParam, measureEvent); if (isDisposed () || item.isDisposed ()) return null; code |= OS.CDRF_NOTIFYPOSTPAINT; } @@ -723,7 +833,7 @@ if ((result !is 0 && (lvItem.state & OS.LVIS_SELECTED) !is 0)) { int clrSelection = -1; if (nmcd.iSubItem is 0) { - if (OS.GetFocus () is handle) { + if (OS.GetFocus () is handle || display.getHighContrast ()) { clrSelection = OS.GetSysColor (OS.COLOR_HIGHLIGHT); } else { if ((style & DWT.HIDE_SELECTION) is 0) { @@ -731,7 +841,7 @@ } } } else { - if (OS.GetFocus () is handle) { + if (OS.GetFocus () is handle || display.getHighContrast ()) { clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT); clrTextBk = clrSelection = OS.GetSysColor (OS.COLOR_HIGHLIGHT); } else { @@ -1172,11 +1282,11 @@ } bits |= width & 0xFFFF; } - int result = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, -1, bits | 0xFFFF0000); - int width = result & 0xFFFF; - int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); - int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); - int itemHeight = (oneItem >> 16) - (empty >> 16); + int /*long*/ result = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, -1, OS.MAKELPARAM (bits, 0xFFFF)); + int width = OS.LOWORD (result); + int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); + int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); + int itemHeight = OS.HIWORD (oneItem) - OS.HIWORD (empty); height += OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0) * itemHeight; if (width is 0) width = DEFAULT_WIDTH; if (height is 0) height = DEFAULT_HEIGHT; @@ -1199,7 +1309,7 @@ /* Use the Explorer theme */ if (EXPLORER_THEME) { - if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) { explorerTheme = true; OS.SetWindowTheme (handle, Display.EXPLORER.ptr, null); } @@ -1208,7 +1318,7 @@ /* Get the header window proc */ if (HeaderProc is null) { auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); - HeaderProc = cast(WNDPROC) OS.GetWindowLong (hwndHeader, OS.GWL_WNDPROC); + HeaderProc = cast(WNDPROC) OS.GetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC); } /* @@ -1237,9 +1347,9 @@ /* Set the checkbox image list */ if ((style & DWT.CHECK) !is 0) { - int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); - int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); - int width = (oneItem >> 16) - (empty >> 16), height = width; + int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); + int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); + int width = OS.HIWORD (oneItem) - OS.HIWORD (empty), height = width; setCheckboxImageList (width, height, false); OS.SendMessage (handle, OS. LVM_SETCALLBACKMASK, OS.LVIS_STATEIMAGEMASK, 0); } @@ -1290,22 +1400,30 @@ * * NOTE: WS_EX_LAYOUTRTL is not supported on Windows NT. */ - if (OS.WIN32_VERSION < OS.VERSION (4, 10)) return; - if ((style & DWT.RIGHT_TO_LEFT) !is 0) { - auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); - int bits2 = OS.GetWindowLong (hwndHeader, OS.GWL_EXSTYLE); - OS.SetWindowLong (hwndHeader, OS.GWL_EXSTYLE, bits2 | OS.WS_EX_LAYOUTRTL); + if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) { + if ((style & DWT.RIGHT_TO_LEFT) !is 0) { + auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); + int bits2 = OS.GetWindowLong (hwndHeader, OS.GWL_EXSTYLE); + OS.SetWindowLong (hwndHeader, OS.GWL_EXSTYLE, bits2 | OS.WS_EX_LAYOUTRTL); + auto hwndTooltop = cast(HWND)OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0); + int bits3 = OS.GetWindowLong (hwndTooltop, OS.GWL_EXSTYLE); + OS.SetWindowLong (hwndTooltop, OS.GWL_EXSTYLE, bits3 | OS.WS_EX_LAYOUTRTL); + } } } void createHeaderToolTips () { static if (OS.IsWinCE) return; if (headerToolTipHandle !is null) return; + int bits = 0; + if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) { + if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL; + } headerToolTipHandle = OS.CreateWindowEx ( - 0, + bits, OS.TOOLTIPS_CLASS.ptr, null, - 0, + OS.TTS_NOPREFIX, OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, handle, null, @@ -1382,11 +1500,10 @@ item.cellForeground = temp; } if (item.cellFont !is null) { - auto cellFont = item.cellFont; - HFONT[] temp = new HFONT[]( columnCount + 1 ); + Font [] cellFont = item.cellFont; + Font [] temp = new Font [columnCount + 1]; System.arraycopy (cellFont, 0, temp, 0, index); System.arraycopy (cellFont, index, temp, index + 1, columnCount - index); - temp [index] = cast(HFONT)-1; item.cellFont = temp; } } @@ -1435,7 +1552,18 @@ } else { OS.SendMessage (handle, OS.LVM_SETCOLUMNWIDTH, 0, 0); } - if ((parent.style & DWT.VIRTUAL) is 0) { + /* + * Bug in Windows. Despite the fact that every item in the + * table always has LPSTR_TEXTCALLBACK, Windows caches the + * bounds for the selected items. This means that + * when you change the string to be something else, Windows + * correctly asks you for the new string but when the item + * is selected, the selection draws using the bounds of the + * previous item. The fix is to reset LPSTR_TEXTCALLBACK + * even though it has not changed, causing Windows to flush + * cached bounds. + */ + if ((style & DWT.VIRTUAL) is 0) { LVITEM lvItem; lvItem.mask = OS.LVIF_TEXT | OS.LVIF_IMAGE; lvItem.pszText = OS.LPSTR_TEXTCALLBACK; @@ -1713,7 +1841,18 @@ OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, &hdItem); } } - if ((parent.style & DWT.VIRTUAL) is 0) { + /* + * Bug in Windows. Despite the fact that every item in the + * table always has LPSTR_TEXTCALLBACK, Windows caches the + * bounds for the selected items. This means that + * when you change the string to be something else, Windows + * correctly asks you for the new string but when the item + * is selected, the selection draws using the bounds of the + * previous item. The fix is to reset LPSTR_TEXTCALLBACK + * even though it has not changed, causing Windows to flush + * cached bounds. + */ + if ((style & DWT.VIRTUAL) is 0) { LVITEM lvItem; lvItem.mask = OS.LVIF_TEXT | OS.LVIF_IMAGE; lvItem.pszText = OS.LPSTR_TEXTCALLBACK; @@ -1781,8 +1920,8 @@ item.cellForeground = temp; } if (item.cellFont !is null) { - HFONT [] cellFont = item.cellFont; - HFONT [] temp = new HFONT[]( columnCount ); + Font [] cellFont = item.cellFont; + Font [] temp = new Font [columnCount]; System.arraycopy (cellFont, 0, temp, 0, index); System.arraycopy (cellFont, index + 1, temp, index, columnCount - index); item.cellFont = temp; @@ -1861,7 +2000,7 @@ if (index is count) return; setDeferResize (true); ignoreSelect = ignoreShrink = true; - int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0); + int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0); ignoreSelect = ignoreShrink = false; if (code is 0) error (DWT.ERROR_ITEM_NOT_REMOVED); System.arraycopy (items, index + 1, items, index, --count - index); @@ -2186,8 +2325,33 @@ public TableItem getItem (Point point) { checkWidget (); if (point is null) error (DWT.ERROR_NULL_ARGUMENT); + int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); + if (count is 0) return null; LVHITTESTINFO pinfo; - pinfo.pt.x = point.x; pinfo.pt.y = point.y; + pinfo.pt.x = point.x; + pinfo.pt.y = point.y; + if ((style & DWT.FULL_SELECTION) is 0) { + if (hooks (DWT.MeasureItem)) { + OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo); + if (pinfo.iItem is -1) { + RECT rect; + rect.left = OS.LVIR_ICON; + ignoreCustomDraw = true; + int /*long*/ code = OS.SendMessage (handle, OS.LVM_GETITEMRECT, 0, &rect); + ignoreCustomDraw = false; + if (code !is 0) { + pinfo.pt.x = rect.left; + OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo); + } + } + if (pinfo.iItem !is -1 && pinfo.iSubItem is 0) { + if (hitTestSelection (pinfo.iItem, pinfo.pt.x, pinfo.pt.y)) { + return _getItem (pinfo.iItem); + } + } + return null; + } + } OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo); if (pinfo.iItem !is -1) { /* @@ -2235,7 +2399,7 @@ /** * Returns the height of the area which would be used to - * display one of the items in the receiver's. + * display one of the items in the receiver. * * @return the height of one item * @@ -2246,9 +2410,9 @@ */ public int getItemHeight () { checkWidget (); - int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); - int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); - return (oneItem >> 16) - (empty >> 16); + int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); + int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); + return OS.HIWORD (oneItem) - OS.HIWORD (empty); } /** @@ -2486,6 +2650,28 @@ return false; } +bool hitTestSelection (int index, int x, int y) { + int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); + if (count is 0) return false; + if (!hooks (DWT.MeasureItem)) return false; + bool result = false; + if (0 <= index && index < count) { + TableItem item = _getItem (index); + auto hDC = OS.GetDC (handle); + HFONT oldFont, newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); + if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont); + auto hFont = item.fontHandle (0); + if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); + Event event = sendMeasureItemEvent (item, index, 0, hDC); + if (event.getBounds ().contains (x, y)) result = true; + if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); + if (newFont !is null) OS.SelectObject (hDC, oldFont); + OS.ReleaseDC (handle, hDC); +// if (isDisposed () || item.isDisposed ()) return false; + } + return result; +} + int imageIndex (Image image, int column) { if (image is null) return OS.I_IMAGENONE; if (column is 0) { @@ -2613,6 +2799,15 @@ return -1; } +bool isCustomToolTip () { + return hooks (DWT.MeasureItem); +} + +bool isOptimizedRedraw () { + if ((style & DWT.H_SCROLL) is 0 || (style & DWT.V_SCROLL) is 0) return false; + return !hasChildren () && !hooks (DWT.Paint) && !filters (DWT.Paint); +} + /** * Returns true if the item is selected, * and false otherwise. Indices out of @@ -2744,7 +2939,7 @@ TableItem item = items [index]; if (item !is null && !item.isDisposed ()) item.release (false); ignoreSelect = ignoreShrink = true; - int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0); + int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0); ignoreSelect = ignoreShrink = false; if (code is 0) error (DWT.ERROR_ITEM_NOT_REMOVED); System.arraycopy (items, index + 1, items, index, --count - index); @@ -2778,7 +2973,7 @@ if (item !is null && !item.isDisposed ()) item.release (false); setDeferResize (true); ignoreSelect = ignoreShrink = true; - int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0); + int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0); ignoreSelect = ignoreShrink = false; if (code is 0) error (DWT.ERROR_ITEM_NOT_REMOVED); System.arraycopy (items, index + 1, items, index, --count - index); @@ -2819,7 +3014,7 @@ TableItem item = items [index]; if (item !is null && !item.isDisposed ()) item.release (false); ignoreSelect = ignoreShrink = true; - int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, start, 0); + int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, start, 0); ignoreSelect = ignoreShrink = false; if (code is 0) break; index++; @@ -2873,7 +3068,7 @@ int index = itemCount - 1; while (index >= 0) { ignoreSelect = ignoreShrink = true; - int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0); + int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, index, 0); ignoreSelect = ignoreShrink = false; if (code is 0) break; --index; @@ -2892,7 +3087,7 @@ if (index !is -1) error (DWT.ERROR_ITEM_NOT_REMOVED); } else { ignoreSelect = ignoreShrink = true; - int code = OS.SendMessage (handle, OS.LVM_DELETEALLITEMS, 0, 0); + int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEALLITEMS, 0, 0); ignoreSelect = ignoreShrink = false; if (code is 0) error (DWT.ERROR_ITEM_NOT_REMOVED); } @@ -3067,10 +3262,8 @@ ignoreSelect = false; } -void sendEraseItemEvent (TableItem item, NMLVCUSTOMDRAW* nmcd, int lParam) { +void sendEraseItemEvent (TableItem item, NMLVCUSTOMDRAW* nmcd, int lParam, Event measureEvent) { auto hDC = nmcd.nmcd.hdc; - auto hFont = item.cellFont !is null ? item.cellFont [nmcd.iSubItem] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = item.font; int clrText = item.cellForeground !is null ? item.cellForeground [nmcd.iSubItem] : -1; if (clrText is -1) clrText = item.foreground; int clrTextBk = -1; @@ -3105,7 +3298,7 @@ } if (OS.IsWindowEnabled (handle)) { if (selected && (nmcd.iSubItem is 0 || (style & DWT.FULL_SELECTION) !is 0)) { - if (OS.GetFocus () is handle) { + if (OS.GetFocus () is handle || display.getHighContrast ()) { drawSelected = true; data.foreground = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT); data.background = clrSelectionBk = OS.GetSysColor (OS.COLOR_HIGHLIGHT); @@ -3120,16 +3313,17 @@ } else { drawBackground = clrTextBk !is -1; /* - * Bug in Windows. When LVM_SETTEXTBKCOLOR or LVM_SETBKCOLOR - * is used to set the background color of the the text or the - * control, the color is not set in the HDC that is provided - * in Custom Draw. The fix is to explicitly set the background - * color. + * Bug in Windows. When LVM_SETTEXTBKCOLOR, LVM_SETBKCOLOR + * or LVM_SETTEXTCOLOR is used to set the background color of + * the the text or the control, the color is not set in the HDC + * that is provided in Custom Draw. The fix is to explicitly + * set the color. */ - if (clrTextBk is -1) { + if (clrText is -1 || clrTextBk is -1) { Control control = findBackgroundControl (); if (control is null) control = this; - clrTextBk = control.getBackgroundPixel (); + if (clrText is -1) clrText = control.getForegroundPixel (); + if (clrTextBk is -1) clrTextBk = control.getBackgroundPixel (); } data.foreground = clrText !is -1 ? clrText : OS.GetTextColor (hDC); data.background = clrTextBk !is -1 ? clrTextBk : OS.GetBkColor (hDC); @@ -3139,7 +3333,7 @@ data.background = OS.GetSysColor (OS.COLOR_3DFACE); if (selected) clrSelectionBk = data.background; } - data.hFont = hFont; + data.font = item.getFont (nmcd.iSubItem); data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); auto nSavedDC = OS.SaveDC (hDC); GC gc = GC.win32_new (hDC, data); @@ -3158,6 +3352,7 @@ } } } + bool focused = (event.detail & DWT.FOCUSED) !is 0; if (drawHot) event.detail |= DWT.HOT; if (drawSelected) event.detail |= DWT.SELECTED; if (drawBackground) event.detail |= DWT.BACKGROUND; @@ -3196,10 +3391,7 @@ OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof); } } - if (ignoreDrawFocus) { - nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS; - OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof); - } + auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); bool firstColumn = nmcd.iSubItem is OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0); if (ignoreDrawForeground && ignoreDrawHot) { @@ -3208,37 +3400,55 @@ fillBackground (hDC, clrTextBk, &backgroundRect); } } - if (!ignoreDrawHot || (!ignoreDrawSelection && clrSelectionBk !is -1)) { + focusRect = null; + if (!ignoreDrawHot || !ignoreDrawSelection || !ignoreDrawFocus) { + bool fullText = (style & DWT.FULL_SELECTION) !is 0 || !firstColumn; + RECT textRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, false, fullText, false, hDC); + if ((style & DWT.FULL_SELECTION) is 0) { + if (measureEvent !is null) { + textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width); + } + if (!ignoreDrawFocus) { + nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS; + OS.MoveMemory (cast(void*)lParam, &nmcd, NMLVCUSTOMDRAW.sizeof); + focusRect = new RECT; + *focusRect = textRect; + } + } if (explorerTheme) { - bool hot = drawHot; - RECT pClipRect; - OS.SetRect (&pClipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); - RECT rect; - OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); - if ((style & DWT.FULL_SELECTION) !is 0) { - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, count - 1, 0); - RECT headerRect; - OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect); - OS.MapWindowPoints (hwndHeader, handle, cast(POINT*) &headerRect, 2); - rect.left = 0; - rect.right = headerRect.right; - pClipRect.left = cellRect.left; - pClipRect.right += EXPLORER_EXTRA; - } else { - rect.right += EXPLORER_EXTRA; - pClipRect.right += EXPLORER_EXTRA; + if (!ignoreDrawHot || (!ignoreDrawSelection && clrSelectionBk !is -1)) { + bool hot = drawHot; + RECT pClipRect; + OS.SetRect (&pClipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); + RECT rect; + OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); + if ((style & DWT.FULL_SELECTION) !is 0) { + int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); + int index = OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, count - 1, 0); + RECT headerRect; + OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect); + OS.MapWindowPoints (hwndHeader, handle, cast(POINT*) &headerRect, 2); + rect.left = 0; + rect.right = headerRect.right; + pClipRect.left = cellRect.left; + pClipRect.right += EXPLORER_EXTRA; + } else { + rect.right += EXPLORER_EXTRA; + pClipRect.right += EXPLORER_EXTRA; + } + auto hTheme = OS.OpenThemeData (handle, Display.LISTVIEW.ptr); + int iStateId = selected ? OS.LISS_SELECTED : OS.LISS_HOT; + if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.LISS_SELECTEDNOTFOCUS; + OS.DrawThemeBackground (hTheme, hDC, OS.LVP_LISTITEM, iStateId, &rect, &pClipRect); + OS.CloseThemeData (hTheme); } - auto hTheme = OS.OpenThemeData (handle, Display.LISTVIEW.ptr); - int iStateId = selected ? OS.LISS_SELECTED : OS.LISS_HOT; - if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.LISS_SELECTEDNOTFOCUS; - OS.DrawThemeBackground (hTheme, hDC, OS.LVP_LISTITEM, iStateId, &rect, &pClipRect); - OS.CloseThemeData (hTheme); } else { - bool fullText = ((style & DWT.FULL_SELECTION) !is 0 || !firstColumn); - RECT textRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, false, fullText, false, hDC); - fillBackground (hDC, clrSelectionBk, &textRect); - } + if (!ignoreDrawSelection && clrSelectionBk !is -1) fillBackground (hDC, clrSelectionBk, &textRect); + } + } + if (focused && ignoreDrawFocus) { + nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS; + OS.MoveMemory (lParam, nmcd, NMLVCUSTOMDRAW.sizeof); } if (ignoreDrawForeground) { RECT clipRect = item.getBounds (nmcd.nmcd.dwItemSpec, nmcd.iSubItem, true, true, true, false, hDC); @@ -3248,13 +3458,40 @@ } } -Event sendMeasureItemEvent (TableItem item, int row, int column, HDC hDC) { - auto hFont = item.cellFont !is null ? item.cellFont [column] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = item.font; +Event sendEraseItemEvent (TableItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* cellRect) { + int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc); + RECT* insetRect = toolTipInset (cellRect); + OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null); GCData data = new GCData (); data.device = display; - data.hFont = hFont; - auto nSavedDC = OS.SaveDC (hDC); + data.foreground = OS.GetTextColor (nmcd.nmcd.hdc); + data.background = OS.GetBkColor (nmcd.nmcd.hdc); + data.font = item.getFont (column); + data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); + GC gc = GC.win32_new (nmcd.nmcd.hdc, data); + Event event = new Event (); + event.item = item; + event.index = column; + event.gc = gc; + event.detail |= DWT.FOREGROUND; + event.x = cellRect.left; + event.y = cellRect.top; + event.width = cellRect.right - cellRect.left; + event.height = cellRect.bottom - cellRect.top; + //gc.setClipping (event.x, event.y, event.width, event.height); + sendEvent (DWT.EraseItem, event); + event.gc = null; + //int newTextClr = data.foreground; + gc.dispose (); + OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC); + return event; +} + +Event sendMeasureItemEvent (TableItem item, int row, int column, HDC hDC) { + GCData data = new GCData (); + data.device = display; + data.font = item.getFont (column); + int nSavedDC = OS.SaveDC (hDC); GC gc = GC.win32_new (hDC, data); RECT itemRect = item.getBounds (row, column, true, true, false, false, hDC); Event event = new Event (); @@ -3281,7 +3518,16 @@ return event; } -LRESULT sendMouseDownEvent (int type, int button, int msg, int wParam, int lParam) { +LRESULT sendMouseDownEvent (int type, int button, int msg, int /*long*/ wParam, int /*long*/ lParam) { + Display display = this.display; + display.captureChanged = false; + if (!sendMouseEvent (type, button, handle, msg, wParam, lParam)) { + if (!display.captureChanged && !isDisposed ()) { + if (OS.GetCapture () !is handle) OS.SetCapture (handle); + } + return LRESULT.ZERO; + } + /* * Feature in Windows. Inside WM_LBUTTONDOWN and WM_RBUTTONDOWN, * the widget starts a modal loop to determine if the user wants @@ -3295,16 +3541,30 @@ * the widget does not eat the mouse up. */ LVHITTESTINFO pinfo; - pinfo.pt.x = cast(short) (lParam & 0xFFFF); - pinfo.pt.y = cast(short) (lParam >> 16); + pinfo.pt.x = OS.GET_X_LPARAM (lParam); + pinfo.pt.y = OS.GET_Y_LPARAM (lParam); OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo); - Display display = this.display; - display.captureChanged = false; - if (!sendMouseEvent (type, button, handle, msg, wParam, lParam)) { - if (!display.captureChanged && !isDisposed ()) { - if (OS.GetCapture () !is handle) OS.SetCapture (handle); - } - return LRESULT.ZERO; + if ((style & DWT.FULL_SELECTION) is 0) { + if (hooks (DWT.MeasureItem)) { + OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo); + if (pinfo.iItem is -1) { + int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); + if (count !is 0) { + RECT rect; + rect.left = OS.LVIR_ICON; + ignoreCustomDraw = true; + int /*long*/ code = OS.SendMessage (handle, OS.LVM_GETITEMRECT, 0, &rect); + ignoreCustomDraw = false; + if (code !is 0) { + pinfo.pt.x = rect.left; + OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo); + pinfo.flags &= ~(OS.LVHT_ONITEMICON | OS.LVHT_ONITEMLABEL); + } + } + } else { + if (pinfo.iSubItem !is 0) pinfo.iItem = -1; + } + } } /* @@ -3354,6 +3614,21 @@ forceSelect = true; } } + + /* Determine whether the user has selected an item based on DWT.MeasureItem */ + fullRowSelect = false; + if (pinfo.iItem !is -1) { + if ((style & DWT.FULL_SELECTION) is 0) { + if (hooks (DWT.MeasureItem)) { + fullRowSelect = hitTestSelection (pinfo.iItem, pinfo.pt.x, pinfo.pt.y); + if (fullRowSelect) { + int flags = OS.LVHT_ONITEMICON | OS.LVHT_ONITEMLABEL; + if ((pinfo.flags & flags) !is 0) fullRowSelect = false; + } + } + } + } + /* * Feature in Windows. Inside WM_LBUTTONDOWN and WM_RBUTTONDOWN, * the widget starts a modal loop to determine if the user wants @@ -3366,11 +3641,31 @@ if (!dragDetect) { int flags = OS.LVHT_ONITEMICON | OS.LVHT_ONITEMLABEL; dragDetect = pinfo.iItem is -1 || (pinfo.flags & flags) is 0; - } + if (fullRowSelect) dragDetect = true; + } + + /* + * Temporarily set LVS_EX_FULLROWSELECT to allow drag and drop + * and the mouse to manipulate items based on the results of + * the DWT.MeasureItem event. + */ + if (fullRowSelect) { + OS.UpdateWindow (handle); + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); + OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_FULLROWSELECT, OS.LVS_EX_FULLROWSELECT); + } + dragStarted = false; + display.dragCancelled = false; if (!dragDetect) display.runDragDrop = false; - int code = callWindowProc (handle, msg, wParam, lParam, forceSelect); + int /*long*/ code = callWindowProc (handle, msg, wParam, lParam, forceSelect); if (!dragDetect) display.runDragDrop = true; - if (dragStarted || !dragDetect) { + if (fullRowSelect) { + fullRowSelect = false; + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); + OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_FULLROWSELECT, 0); + } + + if (dragStarted || display.dragCancelled) { if (!display.captureChanged && !isDisposed ()) { if (OS.GetCapture () !is handle) OS.SetCapture (handle); } @@ -3384,7 +3679,6 @@ sendMouseEvent (DWT.MouseUp, button, handle, msg, wParam, lParam); } } - dragStarted = false; return new LRESULT (code); } @@ -3392,9 +3686,7 @@ auto hDC = nmcd.nmcd.hdc; GCData data = new GCData (); data.device = display; - auto hFont = item.cellFont !is null ? item.cellFont [nmcd.iSubItem] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = item.font; - data.hFont = hFont; + data.font = item.getFont (nmcd.iSubItem); /* * Bug in Windows. For some reason, CDIS_SELECTED always set, * even for items that are not selected. The fix is to get @@ -3412,7 +3704,7 @@ } if (OS.IsWindowEnabled (handle)) { if (selected && (nmcd.iSubItem is 0 || (style & DWT.FULL_SELECTION) !is 0)) { - if (OS.GetFocus () is handle) { + if (OS.GetFocus () is handle || display.getHighContrast ()) { drawSelected = true; if (selectionForeground !is -1) { data.foreground = selectionForeground; @@ -3437,16 +3729,17 @@ if (clrTextBk is -1) clrTextBk = item.background; drawBackground = clrTextBk !is -1; /* - * Bug in Windows. When LVM_SETTEXTBKCOLOR or LVM_SETBKCOLOR - * is used to set the background color of the the text or the - * control, the color is not set in the HDC that is provided - * in Custom Draw. The fix is to explicitly set the background - * color. + * Bug in Windows. When LVM_SETTEXTBKCOLOR, LVM_SETBKCOLOR + * or LVM_SETTEXTCOLOR is used to set the background color of + * the the text or the control, the color is not set in the HDC + * that is provided in Custom Draw. The fix is to explicitly + * set the color. */ - if (clrTextBk is -1) { + if (clrText is -1 || clrTextBk is -1) { Control control = findBackgroundControl (); if (control is null) control = this; - clrTextBk = control.getBackgroundPixel (); + if (clrText is -1) clrText = control.getForegroundPixel (); + if (clrTextBk is -1) clrTextBk = control.getBackgroundPixel (); } data.foreground = clrText !is -1 ? clrText : OS.GetTextColor (hDC); data.background = clrTextBk !is -1 ? clrTextBk : OS.GetBkColor (hDC); @@ -3485,21 +3778,56 @@ int cellHeight = cellRect.bottom - cellRect.top; gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight); sendEvent (DWT.PaintItem, event); + if (data.focusDrawn) focusRect = null; event.gc = null; gc.dispose (); OS.RestoreDC (hDC, nSavedDC); } -override void setBackgroundImage (HBITMAP hBitmap) { +Event sendPaintItemEvent (TableItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* itemRect) { + int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc); + RECT* insetRect = toolTipInset (itemRect); + OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null); + GCData data = new GCData (); + data.device = display; + data.font = item.getFont (column); + data.foreground = OS.GetTextColor (nmcd.nmcd.hdc); + data.background = OS.GetBkColor (nmcd.nmcd.hdc); + data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); + GC gc = GC.win32_new (nmcd.nmcd.hdc, data); + Event event = new Event (); + event.item = item; + event.index = column; + event.gc = gc; + event.detail |= DWT.FOREGROUND; + event.x = itemRect.left; + event.y = itemRect.top; + event.width = itemRect.right - itemRect.left; + event.height = itemRect.bottom - itemRect.top; + //gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight); + sendEvent (DWT.PaintItem, event); + event.gc = null; + gc.dispose (); + OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC); + return event; +} + +void setBackgroundImage (HBITMAP hBitmap) { super.setBackgroundImage (hBitmap); - if (!customDraw) setBackgroundTransparent (hBitmap !is null); + if (hBitmap !is null) { + setBackgroundTransparent (true); + } else { + if (!hooks (DWT.MeasureItem) && !hooks (DWT.EraseItem) && !hooks (DWT.PaintItem)) { + setBackgroundTransparent (false); + } + } } override void setBackgroundPixel (int newPixel) { - if (!customDraw) { + int oldPixel = OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0); + if (oldPixel !is OS.CLR_NONE) { if (findImageControl () !is null) return; if (newPixel is -1) newPixel = defaultBackground (); - int oldPixel = OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0); if (oldPixel !is newPixel) { OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, newPixel); OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, newPixel); @@ -3565,7 +3893,11 @@ Control control = findBackgroundControl (); if (control is null) control = this; if (control.backgroundImage is null) { - setBackgroundPixel (control.getBackgroundPixel ()); + int newPixel = control.getBackgroundPixel (); + OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, newPixel); + OS.SendMessage (handle, OS.LVM_SETTEXTBKCOLOR, 0, newPixel); + if ((style & DWT.CHECK) !is 0) fixCheckboxImageListColor (true); + OS.InvalidateRect (handle, null, true); } /* Set LVS_EX_FULLROWSELECT */ @@ -3701,9 +4033,16 @@ if (defer) { if (resizeCount++ is 0) { wasResized = false; + /* + * Feature in Windows. When LVM_SETBKCOLOR is used with CLR_NONE + * to make the background of the table transparent, drawing becomes + * slow. The fix is to temporarily clear CLR_NONE when redraw is + * turned off. + */ if (hooks (DWT.MeasureItem) || hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) { if (drawCount++ is 0 && OS.IsWindowVisible (handle)) { OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); + OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, 0xFFFFFF); } } } @@ -3711,6 +4050,7 @@ if (--resizeCount is 0) { if (hooks (DWT.MeasureItem) || hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) { if (--drawCount is 0 /*&& OS.IsWindowVisible (handle)*/) { + OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, OS.CLR_NONE); OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); static if (OS.IsWinCE) { auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); @@ -4004,7 +4344,7 @@ if (item !is null && !item.isDisposed ()) item.release (false); if (!isVirtual) { ignoreSelect = ignoreShrink = true; - int code = OS.SendMessage (handle, OS.LVM_DELETEITEM, count, 0); + int /*long*/ code = OS.SendMessage (handle, OS.LVM_DELETEITEM, count, 0); ignoreSelect = ignoreShrink = false; if (code is 0) break; } @@ -4241,25 +4581,23 @@ int itemCount = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0); while (index < itemCount) { String string = null; - HFONT font = cast(HFONT)-1; + HFONT hFont = cast(HFONT)-1; if (item !is null) { string = item.text; imageIndent = Math.max (imageIndent, item.imageIndent); - if (item.cellFont !is null) font = item.cellFont [0]; - if (font is cast(HFONT)-1) font = item.font; + hFont = item.fontHandle (0); } else { if (items [index] !is null) { TableItem tableItem = items [index]; string = tableItem.text; imageIndent = Math.max (imageIndent, tableItem.imageIndent); - if (tableItem.cellFont !is null) font = tableItem.cellFont [0]; - if (font is cast(HFONT)-1) font = tableItem.font; + hFont = tableItem.fontHandle (0); } } if (string !is null && string.length !is 0) { - if (font !is cast(HFONT)-1) { + if (hFont !is cast(HFONT)-1) { auto hDC = OS.GetDC (handle); - auto oldFont = OS.SelectObject (hDC, font); + auto oldFont = OS.SelectObject (hDC, hFont); int flags = OS.DT_CALCRECT | OS.DT_SINGLELINE | OS.DT_NOPREFIX; TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false); RECT rect; @@ -4865,8 +5203,31 @@ super.subclass (); if (HeaderProc !is null) { auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); - OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, display.windowProc); - } + OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, display.windowProc); + } +} + +RECT* toolTipInset (RECT* rect) { + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + RECT* insetRect = new RECT; + OS.SetRect (insetRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1); + return insetRect; + } + return rect; +} + +RECT* toolTipRect (RECT* rect) { + RECT* toolRect = new RECT; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + OS.SetRect (toolRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1); + } else { + HWND hwndToolTip = cast(HWND)OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0); + OS.SetRect (toolRect, rect.left, rect.top, rect.right, rect.bottom); + int dwStyle = OS.GetWindowLong (hwndToolTip, OS.GWL_STYLE); + int dwExStyle = OS.GetWindowLong (hwndToolTip, OS.GWL_EXSTYLE); + OS.AdjustWindowRectEx (toolRect, dwStyle, false, dwExStyle); + } + return toolRect; } override String toolTipText (NMTTDISPINFO* hdr) { @@ -4885,7 +5246,7 @@ super.unsubclass (); if (HeaderProc !is null) { auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); - OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc); + OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc); } } @@ -4904,15 +5265,15 @@ */ WNDPROC oldHeaderProc, oldTableProc; auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); - bool fixSubclass = !hasChildren () && !hooks (DWT.Paint) && !filters (DWT.Paint); + bool fixSubclass = isOptimizedRedraw (); if (fixSubclass) { - oldTableProc = cast(WNDPROC) OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TableProc); - oldHeaderProc = cast(WNDPROC) OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc); + oldTableProc = cast(WNDPROC)OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TableProc); + oldHeaderProc = cast(WNDPROC)OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc); } super.update (all); if (fixSubclass) { - OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) oldTableProc); - OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) oldHeaderProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)oldTableProc); + OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)oldHeaderProc); } } @@ -5044,13 +5405,12 @@ } case OS.WM_SETCURSOR: { if (wParam is cast(int)hwnd) { - int hitTest = cast(short) (lParam & 0xFFFF); + int hitTest = cast(short) OS.LOWORD (lParam); if (hitTest is OS.HTCLIENT) { HDHITTESTINFO pinfo; int pos = OS.GetMessagePos (); POINT pt; - pt.x = cast(short) (pos & 0xFFFF); - pt.y = cast(short) (pos >> 16); + OS.POINTSTOPOINT (pt, pos); OS.ScreenToClient (hwnd, &pt); pinfo.pt.x = pt.x; pinfo.pt.y = pt.y; @@ -5070,6 +5430,19 @@ } return callWindowProc (hwnd, msg, wParam, lParam); } + if (msg is Display.DI_GETDRAGIMAGE) { + /* + * Bug in Windows. For some reason, DI_GETDRAGIMAGE + * returns an image that does not contain strings. + * The fix is to disable the table window proc. + * + * NOTE: This only happens on Vista. + */ + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) return 0; + //TEMPORARY CODE + if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) return 0; +// if (getSelectionCount () !is 1) return 0; + } return super.windowProc (hwnd, msg, wParam, lParam); } @@ -5094,7 +5467,7 @@ * This allows the application to cancel an operation that is normally * performed in WM_KEYDOWN from WM_CHAR. */ - int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); return new LRESULT (code); case DWT.CR: /* @@ -5203,18 +5576,18 @@ * NOTE: The header tooltip can subclass the header proc so the * current proc must be restored or header tooltips stop working. */ - int oldHeaderProc = 0, oldTableProc = 0; + int /*long*/ oldHeaderProc = 0, oldTableProc = 0; auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); - bool fixSubclass = !hasChildren () && !hooks (DWT.Paint) && !filters (DWT.Paint); + bool fixSubclass = isOptimizedRedraw (); if (fixSubclass) { - oldTableProc = OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TableProc); - oldHeaderProc = OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc); + oldTableProc = OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TableProc); + oldHeaderProc = OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc); } - int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); result = code is 0 ? LRESULT.ZERO : new LRESULT (code); if (fixSubclass) { - OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldTableProc); - OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, oldHeaderProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldTableProc); + OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, oldHeaderProc); } //FALL THROUGH case OS.VK_UP: @@ -5250,8 +5623,8 @@ * case and avoid calling the window proc. */ LVHITTESTINFO pinfo; - pinfo.pt.x = cast(short) (lParam & 0xFFFF); - pinfo.pt.y = cast(short) (lParam >> 16); + pinfo.pt.x = OS.GET_X_LPARAM (lParam); + pinfo.pt.y = OS.GET_Y_LPARAM (lParam); int index = OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo); Display display = this.display; display.captureChanged = false; @@ -5302,8 +5675,8 @@ /* Look for check/uncheck */ if ((style & DWT.CHECK) !is 0) { LVHITTESTINFO pinfo; - pinfo.pt.x = cast(short) (lParam & 0xFFFF); - pinfo.pt.y = cast(short) (lParam >> 16); + pinfo.pt.x = OS.GET_X_LPARAM (lParam); + pinfo.pt.y = OS.GET_Y_LPARAM (lParam); /* * Note that when the table has LVS_EX_FULLROWSELECT and the * user clicks anywhere on a row except on the check box, all @@ -5422,8 +5795,8 @@ * case and avoid calling the window proc. */ LVHITTESTINFO pinfo; - pinfo.pt.x = cast(short) (lParam & 0xFFFF); - pinfo.pt.y = cast(short) (lParam >> 16); + pinfo.pt.x = OS.GET_X_LPARAM (lParam); + pinfo.pt.y = OS.GET_Y_LPARAM (lParam); OS.SendMessage (handle, OS.LVM_HITTEST, 0, &pinfo); Display display = this.display; display.captureChanged = false; @@ -5507,7 +5880,32 @@ return result; } -override LRESULT WM_SIZE (int wParam, int lParam) { +override LRESULT WM_SETREDRAW (int wParam, int lParam) { + LRESULT result = super.WM_SETREDRAW (wParam, lParam); + if (result !is null) return result; + /* + * Feature in Windows. When LVM_SETBKCOLOR is used with CLR_NONE + * to make the background of the table transparent, drawing becomes + * slow. The fix is to temporarily clear CLR_NONE when redraw is + * turned off. + */ + if (wParam is 1) { + if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) !is OS.CLR_NONE) { + if (hooks (DWT.MeasureItem) || hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) { + OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, OS.CLR_NONE); + } + } + } + int /*long*/ code = callWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam); + if (wParam is 0) { + if (OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0) is OS.CLR_NONE) { + OS.SendMessage (handle, OS.LVM_SETBKCOLOR, 0, 0xFFFFFF); + } + } + return code is 0 ? LRESULT.ZERO : new LRESULT (code); +} + +override LRESULT WM_SIZE (int /*long*/ wParam, int /*long*/ lParam) { if (ignoreResize) return null; if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) { OS.InvalidateRect (handle, null, true); @@ -5525,8 +5923,11 @@ if (findBackgroundControl () is null) { setBackgroundPixel (defaultBackground ()); } else { - if ((style & DWT.CHECK) !is 0) { - fixCheckboxImageListColor (true); + int oldPixel = OS.SendMessage (handle, OS.LVM_GETBKCOLOR, 0, 0); + if (oldPixel !is OS.CLR_NONE) { + if (findImageControl () is null) { + if ((style & DWT.CHECK) !is 0) fixCheckboxImageListColor (true); + } } } return result; @@ -5551,27 +5952,78 @@ } /* - * When there are many columns in a table, scrolling performance - * can be improved by temporarily unsubclassing the window proc - * so that internal messages are dispatched directly to the table. - * If the application expects to see a paint event or has a child - * whose font, foreground or background color might be needed, - * the window proc cannot be unsubclassed + * Feature in Windows. When there are many columns in a table, + * scrolling performance can be improved by unsubclassing the + * window proc so that internal messages are dispatched directly + * to the table. If the application expects to see a paint event + * or has a child whose font, foreground or background color might + * be needed, the window proc cannot be unsubclassed * * NOTE: The header tooltip can subclass the header proc so the * current proc must be restored or header tooltips stop working. */ - int oldHeaderProc = 0, oldTableProc = 0; + WNDPROC oldHeaderProc, oldTableProc; auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); - bool fixSubclass = !hasChildren () && !hooks (DWT.Paint) && !filters (DWT.Paint); + bool fixSubclass = isOptimizedRedraw (); if (fixSubclass) { - oldTableProc = OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int)TableProc); - oldHeaderProc = OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int)HeaderProc); - } + oldTableProc = cast(WNDPROC)OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TableProc); + oldHeaderProc = cast(WNDPROC)OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc); + } + + /* + * Feature in Windows. For some reason, when the table window + * proc processes WM_HSCROLL or WM_VSCROLL when there are many + * columns in the table, scrolling is slow and the table does + * not keep up with the position of the scroll bar. The fix + * is to turn off redraw, scroll, turn redraw back on and redraw + * the entire table. Strangly, redrawing the entire table is + * faster. + */ + bool fixScroll = false; + if (OS.LOWORD (wParam) !is OS.SB_ENDSCROLL) { + if (OS.COMCTL32_MAJOR >= 6) { + if (columnCount > H_SCROLL_LIMIT) { + int rowCount = OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0); + if (rowCount > V_SCROLL_LIMIT) fixScroll = drawCount is 0 && OS.IsWindowVisible (handle); + } + } + } + if (fixScroll) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); LRESULT result = super.WM_HSCROLL (wParam, lParam); + if (fixScroll) { + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); + int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN; + OS.RedrawWindow (handle, null, null, flags); + /* + * Feature in Windows. On Vista only, it is faster to + * compute and answer the data for the visible columns + * of a table when scrolling, rather than just return + * the data for each column when asked. + */ + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + RECT headerRect, rect; + OS.GetClientRect (handle, &rect); + bool [] visible = new bool [columnCount]; + for (int i=0; i= 6) { + if (columnCount > H_SCROLL_LIMIT) { + int rowCount = OS.SendMessage (handle, OS.LVM_GETCOUNTPERPAGE, 0, 0); + if (rowCount > V_SCROLL_LIMIT) fixScroll = drawCount is 0 && OS.IsWindowVisible (handle); + } + } + } + if (fixScroll) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); LRESULT result = super.WM_VSCROLL (wParam, lParam); + if (fixScroll) { + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); + int flags = OS.RDW_ERASE | OS.RDW_FRAME | OS.RDW_INVALIDATE | OS.RDW_ALLCHILDREN; + OS.RedrawWindow (handle, null, null, flags); + /* + * Feature in Windows. On Vista only, it is faster to + * compute and answer the data for the visible columns + * of a table when scrolling, rather than just return + * the data for each column when asked. + */ + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + RECT headerRect, rect; + OS.GetClientRect (handle, &rect); + bool [] visible = new bool [columnCount]; + for (int i=0; i> 16) - (empty >> 16); + int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); + int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); + int itemHeight = OS.HIWORD (oneItem) - OS.HIWORD (empty); if (code is OS.SB_LINEDOWN) { clientRect.top = clientRect.bottom - itemHeight - GRID_WIDTH; } else { @@ -5670,9 +6173,9 @@ MEASUREITEMSTRUCT* struct_ = cast(MEASUREITEMSTRUCT*)lParam; //OS.MoveMemory (struct_, lParam, MEASUREITEMSTRUCT.sizeof); if (itemHeight is -1) { - int empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); - int oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); - struct_.itemHeight = (oneItem >> 16) - (empty >> 16); + int /*long*/ empty = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 0, 0); + int /*long*/ oneItem = OS.SendMessage (handle, OS.LVM_APPROXIMATEVIEWRECT, 1, 0); + struct_.itemHeight = OS.HIWORD (oneItem) - OS.HIWORD (empty); } else { struct_.itemHeight = itemHeight; } @@ -5681,196 +6184,17 @@ } override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) { - auto hwndHeader = cast(HWND) OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); + HWND hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.LVM_GETTOOLTIPS, 0, 0); + if (hdr.hwndFrom is hwndToolTip) { + LRESULT result = wmNotifyToolTip (hdr, wParam, lParam); + if (result !is null) return result; + } + HWND hwndHeader = cast(HWND)OS.SendMessage (handle, OS.LVM_GETHEADER, 0, 0); if (hdr.hwndFrom is hwndHeader) { - /* - * Feature in Windows. On NT, the automatically created - * header control is created as a UNICODE window, not an - * ANSI window despite the fact that the parent is created - * as an ANSI window. This means that it sends UNICODE - * notification messages to the parent window on NT for - * no good reason. The data and size in the NMHEADER and - * HDITEM structs is identical between the platforms so no - * different message is actually necessary. Despite this, - * Windows sends different messages. The fix is to look - * for both messages, despite the platform. This works - * because only one will be sent on either platform, never - * both. - */ - switch (hdr.code) { - case OS.HDN_BEGINTRACKW: - case OS.HDN_BEGINTRACKA: - case OS.HDN_DIVIDERDBLCLICKW: - case OS.HDN_DIVIDERDBLCLICKA: { - if (columnCount is 0) return LRESULT.ONE; - NMHEADER* phdn = cast(NMHEADER*)lParam; - //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof); - TableColumn column = columns [phdn.iItem]; - if (column !is null && !column.getResizable ()) { - return LRESULT.ONE; - } - ignoreColumnMove = true; - switch (hdr.code) { - case OS.HDN_DIVIDERDBLCLICKW: - case OS.HDN_DIVIDERDBLCLICKA: - /* - * Bug in Windows. When the first column of a table does not - * have an image and the user double clicks on the divider, - * Windows packs the column but does not take into account - * the empty space left for the image. The fix is to measure - * each items ourselves rather than letting Windows do it. - */ - bool fixPack = phdn.iItem is 0 && !firstColumnImage; - if (column !is null && (fixPack || hooks (DWT.MeasureItem))) { - column.pack (); - return LRESULT.ONE; - } - default: - } - break; - } - case OS.NM_RELEASEDCAPTURE: { - if (!ignoreColumnMove) { - for (int i=0; i 0) { - int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); - if ((bits & OS.LVS_EX_GRIDLINES) !is 0) { - RECT rect; - OS.GetClientRect (handle, &rect); - rect.right = rect.left + width; - OS.InvalidateRect (handle, &rect, true); - } - } - lastWidth = width; - if (!ignoreColumnResize) { - NMHEADER* phdn = cast(NMHEADER*)lParam; - //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof); - if (phdn.pitem !is null) { - HDITEM* pitem = cast(HDITEM*)phdn.pitem; - //OS.MoveMemory (pitem, phdn.pitem, HDITEM.sizeof); - if ((pitem.mask & OS.HDI_WIDTH) !is 0) { - TableColumn column = columns [phdn.iItem]; - if (column !is null) { - column.updateToolTip (phdn.iItem); - column.sendEvent (DWT.Resize); - if (isDisposed ()) return LRESULT.ZERO; - /* - * It is possible (but unlikely), that application - * code could have disposed the column in the move - * event. If this happens, process the move event - * for those columns that have not been destroyed. - */ - TableColumn [] newColumns = new TableColumn [columnCount]; - System.arraycopy (columns, 0, newColumns, 0, columnCount); - int [] order = new int [columnCount]; - OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, order.ptr); - bool moved = false; - for (int i=0; i= 0) break; dragStarted = true; if (hdr.code is OS.LVN_BEGINDRAG) { int pos = OS.GetMessagePos (); POINT pt; - pt.x = cast(short) (pos & 0xFFFF); - pt.y = cast(short) (pos >> 16); + OS.POINTSTOPOINT (pt, pos); OS.ScreenToClient (handle, &pt); sendDragEvent (1, pt.x, pt.y); } @@ -6092,6 +6424,11 @@ break; } case OS.LVN_ITEMCHANGED: { + if (fullRowSelect) { + fullRowSelect = false; + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); + OS.SendMessage (handle, OS.LVM_SETEXTENDEDLISTVIEWSTYLE, OS.LVS_EX_FULLROWSELECT, 0); + } if (!ignoreSelect) { NMLISTVIEW* pnmlv = cast(NMLISTVIEW*)lParam; //OS.MoveMemory (pnmlv, lParam, NMLISTVIEW.sizeof); @@ -6164,5 +6501,365 @@ return super.wmNotifyChild (hdr, wParam, lParam); } -} - +LRESULT wmNotifyHeader (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) { + /* + * Feature in Windows. On NT, the automatically created + * header control is created as a UNICODE window, not an + * ANSI window despite the fact that the parent is created + * as an ANSI window. This means that it sends UNICODE + * notification messages to the parent window on NT for + * no good reason. The data and size in the NMHEADER and + * HDITEM structs is identical between the platforms so no + * different message is actually necessary. Despite this, + * Windows sends different messages. The fix is to look + * for both messages, despite the platform. This works + * because only one will be sent on either platform, never + * both. + */ + switch (hdr.code) { + case OS.HDN_BEGINTRACKW: + case OS.HDN_BEGINTRACKA: + case OS.HDN_DIVIDERDBLCLICKW: + case OS.HDN_DIVIDERDBLCLICKA: { + if (columnCount is 0) return LRESULT.ONE; + NMHEADER* phdn = cast(NMHEADER*)lParam; + TableColumn column = columns [phdn.iItem]; + if (column !is null && !column.getResizable ()) { + return LRESULT.ONE; + } + ignoreColumnMove = true; + switch (hdr.code) { + case OS.HDN_DIVIDERDBLCLICKW: + case OS.HDN_DIVIDERDBLCLICKA: + /* + * Bug in Windows. When the first column of a table does not + * have an image and the user double clicks on the divider, + * Windows packs the column but does not take into account + * the empty space left for the image. The fix is to measure + * each items ourselves rather than letting Windows do it. + */ + bool fixPack = phdn.iItem is 0 && !firstColumnImage; + if (column !is null && (fixPack || hooks (DWT.MeasureItem))) { + column.pack (); + return LRESULT.ONE; + } + default: + } + break; + } + case OS.NM_RELEASEDCAPTURE: { + if (!ignoreColumnMove) { + for (int i=0; i 0) { + int bits = OS.SendMessage (handle, OS.LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); + if ((bits & OS.LVS_EX_GRIDLINES) !is 0) { + RECT rect; + OS.GetClientRect (handle, &rect); + rect.right = rect.left + width; + OS.InvalidateRect (handle, &rect, true); + } + } + lastWidth = width; + if (!ignoreColumnResize) { + NMHEADER* phdn = cast(NMHEADER*)lParam; + if (phdn.pitem !is null) { + HDITEM* pitem = cast(HDITEM*)phdn.pitem; + if ((pitem.mask & OS.HDI_WIDTH) !is 0) { + TableColumn column = columns [phdn.iItem]; + if (column !is null) { + column.updateToolTip (phdn.iItem); + column.sendEvent (DWT.Resize); + if (isDisposed ()) return LRESULT.ZERO; + /* + * It is possible (but unlikely), that application + * code could have disposed the column in the move + * event. If this happens, process the move event + * for those columns that have not been destroyed. + */ + TableColumn [] newColumns = new TableColumn [columnCount]; + System.arraycopy (columns, 0, newColumns, 0, columnCount); + int [] order = new int [columnCount]; + OS.SendMessage (handle, OS.LVM_GETCOLUMNORDERARRAY, columnCount, order.ptr); + bool moved = false; + for (int i=0; i cellRect.right) { + //TEMPORARY CODE + String string = " "; +// String string = null; +// if (pinfo.iSubItem is 0) { +// string = item.text; +// } else { +// String [] strings = item.strings; +// if (strings !is null) string = strings [pinfo.iSubItem]; +// } + if (string !is null) { + Shell shell = getShell (); + wchar [] chars = StrToTCHARs(string, true ); + if (hdr.code is OS.TTN_GETDISPINFOA) { + char [] bytes = new char [chars.length * 2]; + OS.WideCharToMultiByte (getCodePage (), 0, chars.ptr, chars.length, bytes.ptr, bytes.length, null, null); + shell.setToolTipText (lpnmtdi, bytes); + OS.MoveMemory (lParam, cast(NMTTDISPINFOA*)lpnmtdi, NMTTDISPINFOA.sizeof); + } else { + shell.setToolTipText (lpnmtdi, chars); + OS.MoveMemory (lParam, cast(NMTTDISPINFOW*)lpnmtdi, NMTTDISPINFOW.sizeof); + } + } + } + } + } + if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); + if (newFont !is null) OS.SelectObject (hDC, oldFont); + OS.ReleaseDC (handle, hDC); + } + } + return new LRESULT (code); + } + } + return null; +} + +LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW* nmcd, int /*long*/ lParam) { + if (OS.IsWinCE) return null; + switch (nmcd.nmcd.dwDrawStage) { + case OS.CDDS_PREPAINT: { + if (isCustomToolTip ()) { + //TEMPORARY CODE +// nmcd.uDrawFlags |= OS.DT_CALCRECT; +// OS.MoveMemory (lParam, nmcd, NMTTCUSTOMDRAW.sizeof); + return new LRESULT (OS.CDRF_NOTIFYPOSTPAINT | OS.CDRF_NEWFONT); + } + break; + } + case OS.CDDS_POSTPAINT: { + LVHITTESTINFO pinfo; + int pos = OS.GetMessagePos (); + POINT pt; + OS.POINTSTOPOINT (pt, pos); + OS.ScreenToClient (handle, &pt); + pinfo.pt.x = pt.x; + pinfo.pt.y = pt.y; + if (OS.SendMessage (handle, OS.LVM_SUBITEMHITTEST, 0, &pinfo) !is -1) { + TableItem item = _getItem (pinfo.iItem); + auto hDC = OS.GetDC (handle); + auto hFont = item.fontHandle (pinfo.iSubItem); + if (cast(int)hFont is -1) hFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); + auto oldFont = cast(HFONT)OS.SelectObject (hDC, hFont); + bool drawForeground = true; + RECT cellRect = item.getBounds (pinfo.iItem, pinfo.iSubItem, true, true, false, false, hDC); + if (hooks (DWT.EraseItem)) { + Event event = sendEraseItemEvent (item, nmcd, pinfo.iSubItem, &cellRect); + if (isDisposed () || item.isDisposed ()) break; + if (event.doit) { + drawForeground = (event.detail & DWT.FOREGROUND) !is 0; + } else { + drawForeground = false; + } + } + if (drawForeground) { + int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc); + int gridWidth = getLinesVisible () ? Table.GRID_WIDTH : 0; + RECT* insetRect = toolTipInset (&cellRect); + OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null); + GCData data = new GCData (); + data.device = display; + data.foreground = OS.GetTextColor (nmcd.nmcd.hdc); + data.background = OS.GetBkColor (nmcd.nmcd.hdc); + data.font = Font.win32_new (display, hFont); + GC gc = GC.win32_new (nmcd.nmcd.hdc, data); + int x = cellRect.left; + if (pinfo.iSubItem !is 0) x -= gridWidth; + Image image = item.getImage (pinfo.iSubItem); + if (image !is null) { + Rectangle rect = image.getBounds (); + RECT imageRect = item.getBounds (pinfo.iItem, pinfo.iSubItem, false, true, false, false, hDC); + Point size = imageList is null ? new Point (rect.width, rect.height) : imageList.getImageSize (); + int y = imageRect.top; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + y = y + Math.max (0, (imageRect.bottom - imageRect.top - size.y) / 2); + } + gc.drawImage (image, rect.x, rect.y, rect.width, rect.height, x, y, size.x, size.y); + x += size.x + INSET + (pinfo.iSubItem is 0 ? -2 : 4); + } else { + x += INSET + 2; + } + String string = item.getText (pinfo.iSubItem); + if (string !is null) { + int flags = OS.DT_NOPREFIX | OS.DT_SINGLELINE | OS.DT_VCENTER; + TableColumn column = columns !is null ? columns [pinfo.iSubItem] : null; + if (column !is null) { + if ((column.style & DWT.CENTER) !is 0) flags |= OS.DT_CENTER; + if ((column.style & DWT.RIGHT) !is 0) flags |= OS.DT_RIGHT; + } + TCHAR[] buffer = StrToTCHARs (getCodePage (), string, false); + RECT textRect; + OS.SetRect (&textRect, x, cellRect.top, cellRect.right, cellRect.bottom); + OS.DrawText (nmcd.nmcd.hdc, buffer.ptr, buffer.length, &textRect, flags); + } + gc.dispose (); + OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC); + } + if (hooks (DWT.PaintItem)) { + RECT itemRect = item.getBounds (pinfo.iItem, pinfo.iSubItem, true, true, false, false, hDC); + sendPaintItemEvent (item, nmcd, pinfo.iSubItem, &itemRect); + } + OS.SelectObject (hDC, oldFont); + OS.ReleaseDC (handle, hDC); + } + } + } + return null; +} +} diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/TableColumn.d --- a/dwt/widgets/TableColumn.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/TableColumn.d Sat May 17 17:34:28 2008 +0200 @@ -104,7 +104,10 @@ * lists the style constants that are applicable to the class. * Style bits are also inherited from superclasses. *

      - * + *

      + * Note that due to a restriction on some platforms, the first column + * is always left aligned. + *

      * @param parent a composite control which will be the parent of the new instance (cannot be null) * @param style the style of control to construct * @param index the zero-relative index to store the receiver in its parent @@ -387,8 +390,7 @@ for (int i=0; iLEFT, RIGHT * or CENTER. - * + *

      + * Note that due to a restriction on some platforms, the first column + * is always left aligned. + *

      * @param alignment the new alignment * * @exception DWTException
        @@ -702,10 +707,12 @@ case DWT.UP: hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTDOWN); hdItem.fmt |= OS.HDF_SORTUP; + if (image is null) hdItem.mask &= ~OS.HDI_IMAGE; break; case DWT.DOWN: hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTUP); hdItem.fmt |= OS.HDF_SORTDOWN; + if (image is null) hdItem.mask &= ~OS.HDI_IMAGE; break; case DWT.NONE: hdItem.fmt &= ~(OS.HDF_SORTUP | OS.HDF_SORTDOWN); @@ -800,7 +807,7 @@ * with spaces. */ auto hHeap = OS.GetProcessHeap (); - TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), fixMnemonic (string), true); + TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), fixMnemonic (string, true), true); int byteCount = buffer.length * TCHAR.sizeof; auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory (pszText, buffer.ptr, byteCount); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/TableItem.d --- a/dwt/widgets/TableItem.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/TableItem.d Sat May 17 17:34:28 2008 +0200 @@ -45,11 +45,11 @@ Table parent; String [] strings; Image [] images; + Font font; + Font [] cellFont; bool checked, grayed, cached; int imageIndent, background = -1, foreground = -1; - HFONT font = cast(HFONT)-1; int [] cellBackground, cellForeground; - HFONT[] cellFont; /** * Constructs a new instance of this class given its parent @@ -143,8 +143,9 @@ images = null; imageIndent = 0; checked = grayed = false; + font = null; background = foreground = -1; - font = cast(HFONT)-1; + cellFont = null; cellBackground = cellForeground = null; cellFont = null; if ((parent.style & DWT.VIRTUAL) !is 0) cached = false; @@ -155,6 +156,12 @@ releaseHandle (); } +HFONT fontHandle (int index) { + if (cellFont !is null && cellFont [index] !is null) return cellFont [index].handle; + if (font !is null) return font.handle; + return cast(HFONT)-1; +} + /** * Returns the receiver's background color. * @@ -264,8 +271,7 @@ if (code is 0) return RECT.init; if (getText) { int width = 0; - auto hFont = cellFont !is null ? cellFont [column] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = font; + auto hFont = fontHandle (column); if (hFont is cast(HFONT)-1 && hDC is null) { TCHAR* buffer = StrToTCHARz (parent.getCodePage (), text); width = OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer); @@ -444,7 +450,7 @@ public Font getFont () { checkWidget (); if (!parent.checkData (this, true)) error (DWT.ERROR_WIDGET_DISPOSED); - return font is cast(HFONT)-1 ? parent.getFont () : Font.win32_new (display, font); + return font !is null ? font : parent.getFont (); } /** @@ -466,8 +472,8 @@ if (!parent.checkData (this, true)) error (DWT.ERROR_WIDGET_DISPOSED); int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count -1) return getFont (); - auto hFont = (cellFont !is null) ? cellFont [index] : font; - return hFont is cast(HFONT)-1 ? getFont () : Font.win32_new (display, hFont); + if (cellFont is null || cellFont [index] is null) return getFont (); + return cellFont [index]; } /** @@ -711,8 +717,8 @@ super.releaseWidget (); strings = null; images = null; + cellFont = null; cellBackground = cellForeground = null; - cellFont = null; } /** @@ -842,13 +848,11 @@ if (font !is null && font.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } - HFONT hFont = cast(HFONT)-1; - if (font !is null) { - parent.setCustomDraw (true); - hFont = font.handle; - } - if (this.font is hFont) return; - this.font = hFont; + Font oldFont = this.font; + if (oldFont is font) return; + this.font = font; + if (oldFont !is null && oldFont.opEquals (font)) return; + if (font !is null) parent.setCustomDraw (true); if ((parent.style & DWT.VIRTUAL) !is 0) cached = true; /* * Bug in Windows. Despite the fact that every item in the @@ -903,19 +907,15 @@ } int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; - auto hFont = cast(HFONT)-1; - if (font !is null) { - parent.setCustomDraw (true); - hFont = font.handle; + if (cellFont is null) { + if (font is null) return; + cellFont = new Font [count]; } - if (cellFont is null) { - cellFont = new HFONT [count]; - for (int i = 0; i < count; i++) { - cellFont [i] = cast(HFONT)-1; - } - } - if (cellFont [index] is hFont) return; - cellFont [index] = hFont; + Font oldFont = cellFont [index]; + if (oldFont is font) return; + cellFont [index] = font; + if (oldFont !is null && oldFont.opEquals (font)) return; + if (font !is null) parent.setCustomDraw (true); if ((parent.style & DWT.VIRTUAL) !is 0) cached = true; if (index is 0) { /* diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Text.d --- a/dwt/widgets/Text.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Text.d Sat May 17 17:34:28 2008 +0200 @@ -36,6 +36,13 @@ /** * Instances of this class are selectable user interface * objects that allow the user to enter and modify text. + * Text controls can be either single or multi-line. + * When a text control is created with a border, the + * operating system includes a platform specific inset + * around the contents of the control. When created + * without a border, an effort is made to remove the + * inset such that the preferred size of the control + * is the same size as the contents. *

        *

        *
        Styles:
        @@ -166,7 +173,60 @@ override int callWindowProc (HWND hwnd, int msg, int wParam, int lParam) { if (handle is null) return 0; - return OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam); + bool redraw = false; + switch (msg) { + case OS.WM_ERASEBKGND: { + if (findImageControl () !is null) return 0; + break; + } + case OS.WM_HSCROLL: + case OS.WM_VSCROLL: { + redraw = findImageControl () !is null && drawCount is 0 && OS.IsWindowVisible (handle); + if (redraw) OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); + break; + } + case OS.WM_PAINT: { + if (findImageControl () !is null) { + PAINTSTRUCT ps; + auto paintDC = OS.BeginPaint (handle, &ps); + int width = ps.rcPaint.right - ps.rcPaint.left; + int height = ps.rcPaint.bottom - ps.rcPaint.top; + if (width !is 0 && height !is 0) { + auto hDC = OS.CreateCompatibleDC (paintDC); + POINT lpPoint1, lpPoint2; + OS.SetWindowOrgEx (hDC, ps.rcPaint.left, ps.rcPaint.top, &lpPoint1); + OS.SetBrushOrgEx (hDC, ps.rcPaint.left, ps.rcPaint.top, &lpPoint2); + auto hBitmap = OS.CreateCompatibleBitmap (paintDC, width, height); + auto hOldBitmap = OS.SelectObject (hDC, hBitmap); + RECT rect; + OS.SetRect (&rect, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom); + drawBackground (hDC, &rect); + OS.CallWindowProc ( EditProc, hwnd, OS.WM_PAINT, cast(int)hDC, lParam); + OS.SetWindowOrgEx (hDC, lpPoint1.x, lpPoint1.y, null); + OS.SetBrushOrgEx (hDC, lpPoint2.x, lpPoint2.y, null); + OS.BitBlt (paintDC, ps.rcPaint.left, ps.rcPaint.top, width, height, hDC, 0, 0, OS.SRCCOPY); + OS.SelectObject (hDC, hOldBitmap); + OS.DeleteObject (hBitmap); + OS.DeleteObject (hDC); + } + OS.EndPaint (handle, &ps); + return 0; + } + break; + } + } + int /*long*/ code = OS.CallWindowProc (EditProc, hwnd, msg, wParam, lParam); + switch (msg) { + case OS.WM_HSCROLL: + case OS.WM_VSCROLL: { + if (redraw) { + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); + OS.InvalidateRect (handle, null, true); + } + break; + } + } + return code; } override void createHandle () { @@ -420,9 +480,9 @@ * the single-line text widget in an editable combo * box. */ - int margins = OS.SendMessage(handle, OS.EM_GETMARGINS, 0, 0); - rect.x -= margins & 0xFFFF; - rect.width += (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF); + int /*long*/ margins = OS.SendMessage(handle, OS.EM_GETMARGINS, 0, 0); + rect.x -= OS.LOWORD (margins); + rect.width += OS.LOWORD (margins) + OS.HIWORD (margins); if ((style & DWT.H_SCROLL) !is 0) rect.width++; if ((style & DWT.BORDER) !is 0) { rect.x -= 1; @@ -485,8 +545,8 @@ int start, end; OS.SendMessage (handle, OS.EM_GETSEL, &start, &end); if (start !is end ) { - int lParam = (x & 0xFFFF) | ((y << 16) & 0xFFFF0000); - int position = OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam) & 0xFFFF; + int /*long*/ lParam = OS.MAKELPARAM (x, y); + int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam)); if (start <= position && position < end) { if (super.dragDetect (hwnd, x, y, filter, detect, consume)) { if (consume !is null) consume [0] = true; @@ -612,7 +672,7 @@ * pixel coordinates (0,0). */ int position = getCaretPosition (); - int caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0); + int /*long*/ caretPos = OS.SendMessage (handle, OS.EM_POSFROMCHAR, position, 0); if (caretPos is -1) { caretPos = 0; if (position >= OS.GetWindowTextLength (handle)) { @@ -641,7 +701,7 @@ OS.SendMessage (handle, OS.EM_SETSEL, start , end ); } } - return new Point (cast(short) (caretPos & 0xFFFF), cast(short) (caretPos >> 16)); + return new Point (OS.GET_X_LPARAM (caretPos), OS.GET_Y_LPARAM (caretPos)); } /** @@ -902,8 +962,8 @@ /*public*/ int getPosition (Point point) { checkWidget(); if (point is null) error (DWT.ERROR_NULL_ARGUMENT); - int lParam = (point.x & 0xFFFF) | ((point.y << 16) & 0xFFFF0000); - int position = OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam) & 0xFFFF; + int /*long*/ lParam = OS.MAKELPARAM (point.x, point.y); + int position = OS.LOWORD (OS.SendMessage (handle, OS.EM_CHARFROMPOS, 0, lParam)); if (!OS.IsUnicode && OS.IsDBLocale) position = mbcsToWcsPos (position); return position; } @@ -1465,8 +1525,8 @@ if ((flags & OS.SWP_NOSIZE) is 0 && width !is 0) { RECT rect; OS.GetWindowRect (handle, &rect); - int margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0); - int marginWidth = (margins & 0xFFFF) + ((margins >> 16) & 0xFFFF); + int /*long*/ margins = OS.SendMessage (handle, OS.EM_GETMARGINS, 0, 0); + int marginWidth = OS.LOWORD (margins) + OS.HIWORD (margins); if (rect.right - rect.left <= marginWidth) { int start, end; OS.SendMessage (handle, OS.EM_GETSEL, &start, &end); @@ -1804,7 +1864,7 @@ * to round off error, the tab spacing may not be the exact * number of space widths, depending on the font. */ - int width = (getTabWidth (tabs) * 4) / (OS.GetDialogBaseUnits () & 0xFFFF); + int width = (getTabWidth (tabs) * 4) / OS.LOWORD (OS.GetDialogBaseUnits ()); OS.SendMessage (handle, OS.EM_SETTABSTOPS, 1, &width); } @@ -2151,7 +2211,7 @@ * so DLGC_WANTARROWS should not be cleared. */ if ((style & DWT.READ_ONLY) !is 0) { - int code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_GETDLGCODE, wParam, lParam); code &= ~(OS.DLGC_WANTALLKEYS | OS.DLGC_WANTTAB); return new LRESULT (code); } @@ -2177,7 +2237,7 @@ * them to the application. */ ignoreCharacter = true; - int result = callWindowProc (handle, OS.WM_IME_CHAR, wParam, lParam); + int /*long*/ result = callWindowProc (handle, OS.WM_IME_CHAR, wParam, lParam); MSG msg; int flags = OS.PM_REMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE; while (OS.PeekMessage (&msg, handle, OS.WM_CHAR, OS.WM_CHAR, flags)) { @@ -2248,8 +2308,8 @@ */ bool hasMenu = menu !is null && !menu.isDisposed (); if (hasMenu || hooks (DWT.MenuDetect)) { - int x = cast(short) (lParam & 0xFFFF); - int y = cast(short) (lParam >> 16); + int x = OS.GET_X_LPARAM (lParam); + int y = OS.GET_Y_LPARAM (lParam); SHRGINFO shrg; shrg.cbSize = SHRGINFO.sizeof; shrg.hwndClient = handle; @@ -2287,7 +2347,7 @@ return wmClipboard (OS.WM_UNDO, wParam, lParam); } -LRESULT wmClipboard (int msg, int wParam, int lParam) { +LRESULT wmClipboard (int msg, int /*long*/ wParam, int /*long*/ lParam) { if ((style & DWT.READ_ONLY) !is 0) return null; if (!hooks (DWT.Verify) && !filters (DWT.Verify)) return null; bool call = false; @@ -2390,9 +2450,12 @@ } override LRESULT wmCommandChild (int wParam, int lParam) { - int code = wParam >> 16; + int code = OS.HIWORD (wParam); switch (code) { case OS.EN_CHANGE: + if (findImageControl () !is null) { + OS.InvalidateRect (handle, null, true); + } if (ignoreModify) break; /* * It is possible (but unlikely), that application diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/ToolBar.d --- a/dwt/widgets/ToolBar.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/ToolBar.d Sat May 17 17:34:28 2008 +0200 @@ -317,7 +317,7 @@ * bar currently sets this value to 300 so it is not * necessary to set TTM_SETMAXTIPWIDTH. */ -// int hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0); +// int /*long*/ hwndToolTip = OS.SendMessage (handle, OS.TB_GETTOOLTIPS, 0, 0); // OS.SendMessage (hwndToolTip, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF); /* @@ -676,8 +676,8 @@ TBBUTTONINFO info; info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_SIZE; - int size = OS.SendMessage (handle, OS.TB_GETBUTTONSIZE, 0, 0); - info.cx = cast(short) (size & 0xFFFF); + int /*long*/ size = OS.SendMessage (handle, OS.TB_GETBUTTONSIZE, 0, 0); + info.cx = cast(short) OS.LOWORD (size); int index = 0; while (index < items.length) { ToolItem item = items [index]; @@ -685,8 +685,8 @@ index++; } if (index < items.length) { - int padding = OS.SendMessage (handle, OS.TB_GETPADDING, 0, 0); - info.cx += (padding & 0xFFFF) * 2; + int /*long*/ padding = OS.SendMessage (handle, OS.TB_GETPADDING, 0, 0); + info.cx += OS.LOWORD (padding) * 2; } for (int i=0; i> 16); + int newX = OS.GET_X_LPARAM (newPos); + int newY = OS.GET_Y_LPARAM (newPos); if (newX !is oldX || newY !is oldY) { Rectangle [] oldRectangles = rectangles; bool oldStippled = stippled; diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Tree.d --- a/dwt/widgets/Tree.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Tree.d Sat May 17 17:34:28 2008 +0200 @@ -37,6 +37,7 @@ import dwt.widgets.Control; import dwt.widgets.Listener; import dwt.widgets.Widget; +import dwt.widgets.Table; import dwt.dwthelper.utils; @@ -77,12 +78,13 @@ * *

        * Note that although this class is a subclass of Composite, - * it does not make sense to add Control children to it, - * or set a layout on it. + * it does not normally make sense to add Control children to + * it, or set a layout on it, unless implementing something like a cell + * editor. *

        *

        *
        Styles:
        - *
        SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL
        + *
        SINGLE, MULTI, CHECK, FULL_SELECTION, VIRTUAL, NO_SCROLL
        *
        Events:
        *
        Selection, DefaultSelection, Collapse, Expand, SetData, MeasureItem, EraseItem, PaintItem
        *
        @@ -102,9 +104,11 @@ TreeItem [] items; TreeColumn [] columns; + int columnCount; ImageList imageList, headerImageList; TreeItem currentItem; TreeColumn sortColumn; + RECT* focusRect; HWND hwndParent, hwndHeader; HANDLE hAnchor, hInsert, hSelect; int lastID; @@ -177,6 +181,9 @@ * @see DWT#SINGLE * @see DWT#MULTI * @see DWT#CHECK + * @see DWT#FULL_SELECTION + * @see DWT#VIRTUAL + * @see DWT#NO_SCROLL * @see Widget#checkSubclass * @see Widget#getStyle */ @@ -187,15 +194,23 @@ static int checkStyle (int style) { /* - * Feature in Windows. It is not possible to create - * a tree that scrolls and does not have scroll bars. - * The TVS_NOSCROLL style will remove the scroll bars - * but the tree will never scroll. Therefore, no matter - * what style bits are specified, set the H_SCROLL and - * V_SCROLL bits so that the DWT style will match the - * widget that Windows creates. + * Feature in Windows. Even when WS_HSCROLL or + * WS_VSCROLL is not specified, Windows creates + * trees and tables with scroll bars. The fix + * is to set H_SCROLL and V_SCROLL. + * + * NOTE: This code appears on all platforms so that + * applications have consistent scroll bar behavior. */ - style |= DWT.H_SCROLL | DWT.V_SCROLL; + if ((style & DWT.NO_SCROLL) is 0) { + style |= DWT.H_SCROLL | DWT.V_SCROLL; + } + /* + * Note: Windows only supports TVS_NOSCROLL and TVS_NOHSCROLL. + */ + if ((style & DWT.H_SCROLL) !is 0 && (style & DWT.V_SCROLL) is 0) { + style |= DWT.V_SCROLL; + } return checkBits (style, DWT.SINGLE, DWT.MULTI, 0, 0, 0, 0); } @@ -215,10 +230,17 @@ case DWT.PaintItem: { customDraw = true; style |= DWT.DOUBLE_BUFFERED; + if (isCustomToolTip ()) createItemToolTips (); OS.SendMessage (handle, OS.TVM_SETSCROLLTIME, 0, 0); int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); - bits |= OS.TVS_NOTOOLTIPS; - if (eventType is DWT.MeasureItem) bits |= OS.TVS_NOHSCROLL; + if (eventType is DWT.MeasureItem) { + if (explorerTheme) { + int bits1 = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0); + bits1 &= ~OS.TVS_EX_AUTOHSCROLL; + OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, 0, bits1); + } + bits |= OS.TVS_NOHSCROLL; + } /* * Feature in Windows. When the tree has the style * TVS_FULLROWSELECT, the background color for the @@ -419,16 +441,14 @@ } } } - int count = 0; int [] order = null; RECT clientRect; OS.GetClientRect (scrolledHandle (), &clientRect); if (hwndHeader !is null) { OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &clientRect, 2); - count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - if (count !is 0) { - order = new int [count]; - OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, cast(int) order.ptr); + if (columnCount !is 0) { + order = new int [columnCount]; + OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, cast(int) order.ptr); } } int sortIndex = -1, clrSortBk = -1; @@ -442,9 +462,9 @@ } int x = 0; Point size = null; - for (int i=0; i 0 && hwndHeader !is null) { + if (columnCount > 0 && hwndHeader !is null) { HDITEM hdItem; hdItem.mask = OS.HDI_WIDTH; OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); @@ -464,7 +484,7 @@ itemRect.right += EXPLORER_EXTRA + 1; pClipRect.left = itemRect.left; pClipRect.right = itemRect.right; - if (count > 0 && hwndHeader !is null) { + if (columnCount > 0 && hwndHeader !is null) { HDITEM hdItem; hdItem.mask = OS.HDI_WIDTH; OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); @@ -473,11 +493,11 @@ } RECT pRect; OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); - if (count > 0 && hwndHeader !is null) { + if (columnCount > 0 && hwndHeader !is null) { int totalWidth = 0; HDITEM hdItem; hdItem.mask = OS.HDI_WIDTH; - for (int j=0; j clientRect.left) { @@ -579,8 +583,7 @@ backgroundRect = ▭ } int clrText = -1, clrTextBk = -1; - HFONT hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = item.font; + auto hFont = item.fontHandle (index); if (selectionForeground !is -1) clrText = selectionForeground; if (OS.IsWindowEnabled (handle)) { bool drawForeground = false; @@ -623,26 +626,8 @@ if (drawItem) { if (i !is 0) { if (hooks (DWT.MeasureItem)) { - RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC); - int nSavedDC = OS.SaveDC (hDC); - GCData data = new GCData (); - data.device = display; - data.hFont = hFont; - GC gc = GC.win32_new (hDC, data); - Event event = new Event (); - event.item = item; - event.index = index; - event.gc = gc; - event.x = itemRect.left; - event.y = itemRect.top; - event.width = itemRect.right - itemRect.left; - event.height = itemRect.bottom - itemRect.top; - sendEvent (DWT.MeasureItem, event); - event.gc = null; - gc.dispose (); - OS.RestoreDC (hDC, nSavedDC); + sendMeasureItemEvent (item, index, hDC); if (isDisposed () || item.isDisposed ()) break; - if (event.height > getItemHeight ()) setItemHeight (event.height); } if (hooks (DWT.EraseItem)) { RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC); @@ -655,7 +640,7 @@ if (clrText !is -1) data.foreground = clrText; if (clrTextBk !is -1) data.background = clrTextBk; } - data.hFont = hFont; + data.font = item.getFont (index); data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); GC gc = GC.win32_new (hDC, data); Event event = new Event (); @@ -709,12 +694,12 @@ if (!explorerTheme) { drawBackground = true; ignoreDrawBackground = false; - if (handle is OS.GetFocus () && OS.IsWindowEnabled (handle)) { + if ((handle is OS.GetFocus () || display.getHighContrast ()) && OS.IsWindowEnabled (handle)) { clrTextBk = OS.GetSysColor (OS.COLOR_HIGHLIGHT); } else { clrTextBk = OS.GetSysColor (OS.COLOR_3DFACE); } - if (!ignoreFullSelection && index is count - 1) { + if (!ignoreFullSelection && index is columnCount - 1) { RECT* selectionRect = new RECT (); OS.SetRect (selectionRect, backgroundRect.left, backgroundRect.top, nmcd.nmcd.rc.right, backgroundRect.bottom); backgroundRect = selectionRect; @@ -722,11 +707,11 @@ } else { RECT pRect; OS.SetRect (&pRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); - if (count > 0 && hwndHeader !is null) { + if (columnCount > 0 && hwndHeader !is null) { int totalWidth = 0; HDITEM hdItem; hdItem.mask = OS.HDI_WIDTH; - for (int j=0; j 0 && hwndHeader !is null) { - int width = 0; - HDITEM hdItem; - hdItem.mask = OS.HDI_WIDTH; - for (int j=0; j= OS.VERSION (6, 0)) { - clip = true; - } - if (clip) { - clipRect = new RECT (); - HDITEM hdItem; - hdItem.mask = OS.HDI_WIDTH; - OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); - OS.SetRect (clipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom); - } + if (columnCount !is 0) { + bool clip = !printClient; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + clip = true; + } + if (clip) { + clipRect = new RECT (); + HDITEM hdItem; + hdItem.mask = OS.HDI_WIDTH; + OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); + OS.SetRect (clipRect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom); } } int clrText = -1, clrTextBk = -1; @@ -1034,6 +1004,7 @@ } bool selected = isItemSelected (nmcd); bool hot = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_HOT) !is 0; + bool focused = explorerTheme && (nmcd.nmcd.uItemState & OS.CDIS_FOCUS) !is 0; if (OS.IsWindowVisible (handle) && nmcd.nmcd.rc.left < nmcd.nmcd.rc.right && nmcd.nmcd.rc.top < nmcd.nmcd.rc.bottom) { if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); if (linesVisible) { @@ -1042,49 +1013,25 @@ OS.DrawEdge (hDC, &rect, OS.BDR_SUNKENINNER, OS.BF_BOTTOM); } //TODO - BUG - measure and erase sent when first column is clipped + Event measureEvent = null; if (hooks (DWT.MeasureItem)) { - RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC); - int nSavedDC = OS.SaveDC (hDC); - GCData data = new GCData (); - data.device = display; - data.hFont = hFont; - GC gc = GC.win32_new (hDC, data); - Event event = new Event (); - event.item = item; - event.gc = gc; - event.index = index; - event.x = itemRect.left; - event.y = itemRect.top; - event.width = itemRect.right - itemRect.left; - event.height = itemRect.bottom - itemRect.top; - sendEvent (DWT.MeasureItem, event); - event.gc = null; - gc.dispose (); - OS.RestoreDC (hDC, nSavedDC); + measureEvent = sendMeasureItemEvent (item, index, hDC); if (isDisposed () || item.isDisposed ()) return null; - if (hwndHeader !is null) { - if (count is 0) { - if (event.x + event.width > scrollWidth) { - setScrollWidth (scrollWidth = event.x + event.width); - } - } - } - if (event.height > getItemHeight ()) setItemHeight (event.height); } selectionForeground = -1; ignoreDrawForeground = ignoreDrawBackground = ignoreDrawSelection = ignoreDrawFocus = ignoreDrawHot = ignoreFullSelection = false; if (hooks (DWT.EraseItem)) { RECT rect; OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.right, nmcd.nmcd.rc.bottom); - if (OS.IsWindowEnabled (handle) || findImageControl () !is null) { - drawBackground (hDC, &rect); - } else { - fillBackground (hDC, OS.GetBkColor (hDC), &rect); - } RECT cellRect = item.getBounds (index, true, true, true, true, true, hDC); if (clrSortBk !is -1) { - RECT fullRect = item.getBounds (index, true, true, true, true, true, hDC); - drawBackground (hDC, &fullRect, clrSortBk); + drawBackground (hDC, &cellRect, clrSortBk); + } else { + if (OS.IsWindowEnabled (handle) || findImageControl () !is null) { + drawBackground (hDC, &rect); + } else { + fillBackground (hDC, OS.GetBkColor (hDC), &rect); + } } int nSavedDC = OS.SaveDC (hDC); GCData data = new GCData (); @@ -1100,7 +1047,7 @@ if (clrTextBk !is -1) data.background = clrTextBk; } data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - if (hFont !is cast(HFONT)-1) data.hFont = hFont; + data.font = item.getFont (index); GC gc = GC.win32_new (hDC, data); Event event = new Event (); event.index = index; @@ -1115,7 +1062,10 @@ if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0) is nmcd.nmcd.dwItemSpec) { if (handle is OS.GetFocus ()) { int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - if ((uiState & OS.UISF_HIDEFOCUS) is 0) event.detail |= DWT.FOCUSED; + if ((uiState & OS.UISF_HIDEFOCUS) is 0) { + focused = true; + event.detail |= DWT.FOCUSED; + } } } } @@ -1144,11 +1094,14 @@ bool draw = !selected && !hot; if (!explorerTheme && selected) draw = !ignoreDrawSelection; if (draw) { - if (count is 0) { + if (columnCount is 0) { if ((style & DWT.FULL_SELECTION) !is 0) { fillBackground (hDC, clrTextBk, &rect); } else { - RECT textRect = item.getBounds (index, true, false, true, false, true, hDC); + RECT textRect = item.getBounds (index, true, false, false, false, true, hDC); + if (measureEvent !is null) { + textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width); + } fillBackground (hDC, clrTextBk, &textRect); } } else { @@ -1161,7 +1114,25 @@ if (!selected && !hot) { selectionForeground = clrText = OS.GetSysColor (OS.COLOR_HIGHLIGHTTEXT); } - if (!explorerTheme) { + if (explorerTheme) { + if ((style & DWT.FULL_SELECTION) is 0) { + RECT pRect = item.getBounds (index, true, true, false, false, false, hDC); + RECT pClipRect = item.getBounds (index, true, true, true, false, true, hDC); + if (measureEvent !is null) { + pRect.right = Math.min (pClipRect.right, measureEvent.x + measureEvent.width); + } else { + pRect.right += EXPLORER_EXTRA; + pClipRect.right += EXPLORER_EXTRA; + } + pRect.left -= EXPLORER_EXTRA; + pClipRect.left -= EXPLORER_EXTRA; + auto hTheme = OS.OpenThemeData (handle, Display.TREEVIEW.ptr); + int iStateId = selected ? OS.TREIS_SELECTED : OS.TREIS_HOT; + if (OS.GetFocus () !is handle && selected && !hot) iStateId = OS.TREIS_SELECTEDNOTFOCUS; + OS.DrawThemeBackground (hTheme, hDC, OS.TVP_TREEITEM, iStateId, &pRect, &pClipRect); + OS.CloseThemeData (hTheme); + } + } else { /* * Feature in Windows. When the tree has the style * TVS_FULLROWSELECT, the background color for the @@ -1170,13 +1141,16 @@ * is to emulate TVS_FULLROWSELECT. */ if ((style & DWT.FULL_SELECTION) !is 0) { - if ((style & DWT.FULL_SELECTION) !is 0 && count is 0) { + if ((style & DWT.FULL_SELECTION) !is 0 && columnCount is 0) { fillBackground (hDC, OS.GetBkColor (hDC), &rect); } else { fillBackground (hDC, OS.GetBkColor (hDC), &cellRect); } } else { RECT textRect = item.getBounds (index, true, false, false, false, true, hDC); + if (measureEvent !is null) { + textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width); + } fillBackground (hDC, OS.GetBkColor (hDC), &textRect); } } @@ -1203,6 +1177,16 @@ OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof); } } + if (focused && !ignoreDrawFocus && (style & DWT.FULL_SELECTION) is 0) { + RECT textRect = item.getBounds (index, true, explorerTheme, false, false, true, hDC); + if (measureEvent !is null) { + textRect.right = Math.min (cellRect.right, measureEvent.x + measureEvent.width); + } + nmcd.nmcd.uItemState &= ~OS.CDIS_FOCUS; + OS.MoveMemory (lParam, nmcd, NMTVCUSTOMDRAW.sizeof); + if( focusRect is null ) focusRect = new RECT; + *focusRect = textRect; + } if (explorerTheme) { if (selected || (hot && ignoreDrawHot)) nmcd.nmcd.uItemState &= ~OS.CDIS_HOT; OS.MoveMemory (cast(void*)lParam, nmcd, NMTVCUSTOMDRAW.sizeof); @@ -1260,7 +1244,7 @@ if (clrTextBk !is -1) { int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); if ((bits & OS.TVS_FULLROWSELECT) is 0) { - if (count !is 0 && hwndHeader !is null) { + if (columnCount !is 0 && hwndHeader !is null) { RECT rect; HDITEM hdItem; hdItem.mask = OS.HDI_WIDTH; @@ -1268,8 +1252,7 @@ OS.SetRect (&rect, nmcd.nmcd.rc.left, nmcd.nmcd.rc.top, nmcd.nmcd.rc.left + hdItem.cxy, nmcd.nmcd.rc.bottom); if (OS.COMCTL32_MAJOR < 6 || !OS.IsAppThemed ()) { RECT itemRect; - itemRect.left = cast(int) item.handle; - if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, &itemRect) !is 0) { + if (OS.TreeView_GetItemRect (handle, item.handle, &itemRect, true)) { rect.left = Math.min (itemRect.left, rect.right); } } @@ -1329,7 +1312,7 @@ if (clrTextBk !is -1) { if ((style & DWT.FULL_SELECTION) !is 0) { RECT rect; - if (count !is 0) { + if (columnCount !is 0) { HDITEM hdItem; hdItem.mask = OS.HDI_WIDTH; OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); @@ -1406,8 +1389,7 @@ } if (hItem !is null) { RECT rect; - rect.left = cast(int) hItem; - if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) { + if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) { top = rect.bottom; } } @@ -1429,8 +1411,7 @@ RECT rect; HDITEM hdItem; hdItem.mask = OS.HDI_WIDTH; - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - for (int i=0; i= OS.VERSION (6, 0)) { + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) { int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0); if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) style |= DWT.DOUBLE_BUFFERED; } @@ -1674,8 +1654,11 @@ bool checkData (TreeItem item, bool redraw) { if ((style & DWT.VIRTUAL) is 0) return true; - TreeItem parentItem = item.getParentItem (); - return checkData (item, parentItem is null ? indexOf (item) : parentItem.indexOf (item), redraw); + if (!item.cached) { + TreeItem parentItem = item.getParentItem (); + return checkData (item, parentItem is null ? indexOf (item) : parentItem.indexOf (item), redraw); + } + return true; } bool checkData (TreeItem item, int index, bool redraw) { @@ -1713,8 +1696,8 @@ * callers of this method. */ if (drawCount is 0) return false; - int hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); - int hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem); + int /*long*/ hRoot = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); + int /*long*/ hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hItem); while (hParent !is hRoot && hParent !is 0) { hParent = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hParent); } @@ -1770,6 +1753,7 @@ item = tvItem.lParam !is -1 ? items [tvItem.lParam] : null; } if (item !is null) { + if ((style & DWT.VIRTUAL) !is 0 && !item.cached) return; item.clear (); item.redraw (); } @@ -1798,16 +1782,30 @@ checkWidget (); HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); if (hItem is null) return; - TVITEM tvItem; - tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM; - clearAll (hItem, &tvItem, all); + if (all) { + bool redraw = false; + for (int i=0; i= OS.VERSION (6, 0)) { + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) { explorerTheme = true; OS.SetWindowTheme (handle, cast(TCHAR*) Display.EXPLORER, null); int bits = OS.TVS_EX_DOUBLEBUFFER | OS.TVS_EX_FADEINOUTEXPANDOS | OS.TVS_EX_RICHTOOLTIP; @@ -1931,11 +1927,15 @@ void createHeaderToolTips () { static if (OS.IsWinCE) return; if (headerToolTipHandle !is null) return; + int bits = 0; + if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) { + if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits |= OS.WS_EX_LAYOUTRTL; + } headerToolTipHandle = OS.CreateWindowEx ( - 0, + bits, OS.TOOLTIPS_CLASS.ptr, null, - 0, + OS.TTS_NOPREFIX, OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, handle, null, @@ -1954,7 +1954,6 @@ void createItem (TreeColumn column, int index) { if (hwndHeader is null) createParent (); - int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); if (!(0 <= index && index <= columnCount)) error (DWT.ERROR_INVALID_RANGE); if (columnCount is columns.length) { TreeColumn [] newColumns = new TreeColumn [columns.length + 4]; @@ -2009,16 +2008,15 @@ item.cellForeground = temp; } if (item.cellFont !is null) { - HFONT [] cellFont = item.cellFont; - HFONT [] temp = new HFONT [columnCount + 1]; + Font [] cellFont = item.cellFont; + Font [] temp = new Font [columnCount + 1]; System.arraycopy (cellFont, 0, temp, 0, index); System.arraycopy (cellFont, index, temp, index + 1, columnCount- index); - temp [index] = cast(HFONT)-1; item.cellFont = temp; } } } - System.arraycopy (columns, index, columns, index + 1, columnCount - index); + System.arraycopy (columns, index, columns, index + 1, columnCount++ - index); columns [index] = column; /* @@ -2039,11 +2037,13 @@ if (pszText !is null) OS.HeapFree (hHeap, 0, pszText); /* When the first column is created, hide the horizontal scroll bar */ - if (columnCount is 0) { + if (columnCount is 1) { scrollWidth = 0; - int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); - bits |= OS.TVS_NOHSCROLL; - OS.SetWindowLong (handle, OS.GWL_STYLE, bits); + if ((style & DWT.H_SCROLL) !is 0) { + int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); + bits |= OS.TVS_NOHSCROLL; + OS.SetWindowLong (handle, OS.GWL_STYLE, bits); + } /* * Bug in Windows. When TVS_NOHSCROLL is set after items * have been inserted into the tree, Windows shows the @@ -2054,13 +2054,17 @@ if (count !is 0) { static if (!OS.IsWinCE) OS.ShowScrollBar (handle, OS.SB_HORZ, false); } + createItemToolTips (); + if (itemToolTipHandle !is null) { + OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_AUTOMATIC, -1); + } } setScrollWidth (); updateImageList (); updateScrollBar (); /* Redraw to hide the items when the first column is created */ - if (columnCount is 0 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) !is 0) { + if (columnCount is 1 && OS.SendMessage (handle, OS.TVM_GETCOUNT, 0, 0) !is 0) { OS.InvalidateRect (handle, null, true); } @@ -2148,12 +2152,9 @@ items [id] = item; } if (hFirstItem is null) { - switch ( cast(int) hInsertAfter) { - case OS.TVI_FIRST: - case OS.TVI_LAST: - hFirstIndexOf = hLastIndexOf = hFirstItem = hNewItem; - itemCount = lastIndexOf = 0; - default: + if (cast(int)hInsertAfter is OS.TVI_FIRST || cast(int)hInsertAfter is OS.TVI_LAST) { + hFirstIndexOf = hLastIndexOf = hFirstItem = hNewItem; + itemCount = lastIndexOf = 0; } } if (hFirstItem is hFirstIndexOf && itemCount !is -1) itemCount++; @@ -2168,8 +2169,7 @@ if (fixParent) { if (drawCount is 0 && OS.IsWindowVisible (handle)) { RECT rect; - rect.left = cast(int) hParent; - if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) { + if (OS.TreeView_GetItemRect (handle, hParent, &rect, false)) { OS.InvalidateRect (handle, &rect, true); } } @@ -2184,8 +2184,7 @@ if ((style & DWT.VIRTUAL) !is 0) { if (currentItem !is null) { RECT rect; - rect.left = cast(int) hNewItem; - if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) { + if (OS.TreeView_GetItemRect (handle, hNewItem, &rect, false)) { RECT damageRect; bool damaged = cast(bool) OS.GetUpdateRect (handle, &damageRect, true); if (damaged && damageRect.top < rect.bottom) { @@ -2212,28 +2211,36 @@ void createItemToolTips () { static if (OS.IsWinCE) return; if (itemToolTipHandle !is null) return; - int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); - bits |= OS.TVS_NOTOOLTIPS; - OS.SetWindowLong (handle, OS.GWL_STYLE, bits); + int bits1 = OS.GetWindowLong (handle, OS.GWL_STYLE); + bits1 |= OS.TVS_NOTOOLTIPS; + OS.SetWindowLong (handle, OS.GWL_STYLE, bits1); + int bits2 = 0; + if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) { + if ((style & DWT.RIGHT_TO_LEFT) !is 0) bits2 |= OS.WS_EX_LAYOUTRTL; + } + /* + * Feature in Windows. For some reason, when the user + * clicks on a tool tip, it temporarily takes focus, even + * when WS_EX_NOACTIVATE is specified. The fix is to + * use WS_EX_TRANSPARENT, even though WS_EX_TRANSPARENT + * is documented to affect painting, not hit testing. + * + * NOTE: Windows 2000 doesn't have the problem and + * setting WS_EX_TRANSPARENT causes pixel corruption. + */ + if (OS.COMCTL32_MAJOR >= 6) bits2 |= OS.WS_EX_TRANSPARENT; itemToolTipHandle = OS.CreateWindowEx ( - 0, + bits2, OS.TOOLTIPS_CLASS.ptr, null, - 0, + OS.TTS_NOPREFIX | OS.TTS_NOANIMATE | OS.TTS_NOFADE, OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0, handle, null, OS.GetModuleHandle (null), null); if (itemToolTipHandle is null) error (DWT.ERROR_NO_HANDLES); - /* - * Feature in Windows. Despite the fact that the - * tool tip text contains \r\n, the tooltip will - * not honour the new line unless TTM_SETMAXTIPWIDTH - * is set. The fix is to set TTM_SETMAXTIPWIDTH to - * a large value. - */ - OS.SendMessage (itemToolTipHandle, OS.TTM_SETMAXTIPWIDTH, 0, 0x7FFF); + OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0); TOOLINFO lpti; lpti.cbSize = TOOLINFO.sizeof; lpti.hwnd = handle; @@ -2266,7 +2273,7 @@ OS.GetModuleHandle (null), null); if (hwndParent is null) error (DWT.ERROR_NO_HANDLES); - OS.SetWindowLong (hwndParent, OS.GWL_ID, cast(int) hwndParent); + OS.SetWindowLongPtr (hwndParent, OS.GWLP_ID, cast(LONG_PTR)hwndParent); int bits = 0; if (OS.WIN32_VERSION >= OS.VERSION (4, 10)) { bits |= OS.WS_EX_NOINHERITLAYOUT; @@ -2283,7 +2290,7 @@ OS.GetModuleHandle (null), null); if (hwndHeader is null) error (DWT.ERROR_NO_HANDLES); - OS.SetWindowLong (hwndHeader, OS.GWL_ID, cast(int) hwndHeader); + OS.SetWindowLongPtr (hwndHeader, OS.GWLP_ID, cast(LONG_PTR)hwndHeader); if (OS.IsDBLocale) { auto hIMC = OS.ImmGetContext (handle); OS.ImmAssociateContext (hwndParent, hIMC); @@ -2323,7 +2330,6 @@ if (hwndFocus is handle) OS.SetFocus (handle); register (); subclass (); - createItemToolTips (); } override void createWidget () { @@ -2356,6 +2362,34 @@ } /** + * Deselects an item in the receiver. If the item was already + * deselected, it remains deselected. + * + * @param item the item to be deselected + * + * @exception IllegalArgumentException
          + *
        • ERROR_NULL_ARGUMENT - if the item is null
        • + *
        • ERROR_INVALID_ARGUMENT - if the item has been disposed
        • + *
        + * @exception DWTException
          + *
        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
        • + *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • + *
        + * + * @since 3.4 + */ +public void deselect (TreeItem item) { + checkWidget (); + if (item is null) error (DWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + TVITEM tvItem; + tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; + tvItem.stateMask = OS.TVIS_SELECTED; + tvItem.hItem = item.handle; + OS.SendMessage (handle, OS.TVM_SETITEM, 0, cast(int)&tvItem); +} + +/** * Deselects all selected items in the receiver. * * @exception DWTException
          @@ -2375,8 +2409,8 @@ OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); } } else { - int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); - OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); + auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc); if ((style & DWT.VIRTUAL) !is 0) { HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); deselect (hItem, &tvItem, null); @@ -2389,13 +2423,12 @@ } } } - OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc); } } void destroyItem (TreeColumn column) { if (hwndHeader is null) error (DWT.ERROR_ITEM_NOT_REMOVED); - int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); int index = 0; while (index < columnCount) { if (columns [index] is column) break; @@ -2462,8 +2495,8 @@ item.cellForeground = temp; } if (item.cellFont !is null) { - HFONT [] cellFont = item.cellFont; - HFONT [] temp = new HFONT [columnCount]; + Font [] cellFont = item.cellFont; + Font [] temp = new Font [columnCount]; System.arraycopy (cellFont, 0, temp, 0, index); System.arraycopy (cellFont, index + 1, temp, index, columnCount - index); item.cellFont = temp; @@ -2481,10 +2514,13 @@ scrollWidth = 0; if (!hooks (DWT.MeasureItem)) { int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); - bits &= ~OS.TVS_NOHSCROLL; + if ((style & DWT.H_SCROLL) !is 0) bits &= ~OS.TVS_NOHSCROLL; OS.SetWindowLong (handle, OS.GWL_STYLE, bits); OS.InvalidateRect (handle, null, true); } + if (itemToolTipHandle !is null) { + OS.SendMessage (itemToolTipHandle, OS.TTM_SETDELAYTIME, OS.TTDT_INITIAL, 0); + } } else { if (index is 0) { columns [0].style &= ~(DWT.LEFT | DWT.RIGHT | DWT.CENTER); @@ -2552,8 +2588,7 @@ if ((style & DWT.DOUBLE_BUFFERED) is 0) { if (drawCount is 0 && OS.IsWindowVisible (handle)) { RECT rect; - rect.left = cast(int) hItem; - fixRedraw = OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) is 0; + fixRedraw = !OS.TreeView_GetItemRect (handle, hItem, &rect, false); } } if (fixRedraw) { @@ -2599,8 +2634,7 @@ */ if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hParent) is 0) { RECT rect; - rect.left = cast(int) hParent; - if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect) !is 0) { + if (OS.TreeView_GetItemRect (handle, hParent, &rect, false)) { OS.InvalidateRect (handle, &rect, true); } } @@ -2624,6 +2658,21 @@ updateScrollBar (); } +void destroyScrollBar (int type) { + super.destroyScrollBar (type); + int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); + if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) { + bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL); + bits |= OS.TVS_NOSCROLL; + } else { + if ((style & DWT.H_SCROLL) is 0) { + bits &= ~OS.WS_HSCROLL; + bits |= OS.TVS_NOHSCROLL; + } + } + OS.SetWindowLong (handle, OS.GWL_STYLE, bits); +} + override void enableDrag (bool enabled) { int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); if (enabled && hooks (DWT.DragDetect)) { @@ -2672,6 +2721,66 @@ updateFullSelection (); } +bool findCell (int x, int y, inout TreeItem item, inout int index, inout RECT cellRect, inout RECT itemRect) { + bool found = false; + TVHITTESTINFO lpht; + lpht.pt.x = x; + lpht.pt.y = y; + OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); + if (lpht.hItem !is null) { + item = _getItem (lpht.hItem); + POINT pt; + pt.x = x; + pt.y = y; + auto hDC = OS.GetDC (handle); + HFONT oldFont; + auto newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); + if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont); + RECT rect; + if (hwndParent !is null) { + OS.GetClientRect (hwndParent, &rect); + OS.MapWindowPoints (hwndParent, handle, cast(POINT*)&rect, 2); + } else { + OS.GetClientRect (handle, &rect); + } + int count = Math.max (1, columnCount); + int [] order = new int [count]; + if (hwndHeader !is null) OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, cast(int) order.ptr); + index = 0; + bool quit = false; + while (index < count && !quit) { + auto hFont = item.fontHandle (order [index]); + if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); + cellRect = item.getBounds (order [index], true, false, true, false, true, hDC); + if (cellRect.left > rect.right) { + quit = true; + } else { + cellRect.right = Math.min (cellRect.right, rect.right); + if (OS.PtInRect ( &cellRect, pt)) { + if (isCustomToolTip ()) { + Event event = sendMeasureItemEvent (item, order [index], hDC); + if (isDisposed () || item.isDisposed ()) break; + //itemRect [0] = new RECT (); + itemRect.left = event.x; + itemRect.right = event.x + event.width; + itemRect.top = event.y; + itemRect.bottom = event.y + event.height; + } else { + itemRect = item.getBounds (order [index], true, false, false, false, false, hDC); + } + if (itemRect.right > cellRect.right) found = true; + quit = true; + } + } + if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); + if (!found) index++; + } + if (newFont !is null) OS.SelectObject (hDC, oldFont); + OS.ReleaseDC (handle, hDC); + } + return found; +} + int findIndex (HANDLE hFirstItem, HANDLE hItem) { if (hFirstItem is null) return -1; if (hFirstItem is hFirstIndexOf) { @@ -2903,9 +3012,7 @@ */ public TreeColumn getColumn (int index) { checkWidget (); - if (hwndHeader is null) error (DWT.ERROR_INVALID_RANGE); - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - if (!(0 <= index && index < count)) error (DWT.ERROR_INVALID_RANGE); + if (!(0 <= index && index < columnCount)) error (DWT.ERROR_INVALID_RANGE); return columns [index]; } @@ -2927,8 +3034,7 @@ */ public int getColumnCount () { checkWidget (); - if (hwndHeader is null) return 0; - return OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); + return columnCount; } /** @@ -2961,10 +3067,9 @@ */ public int[] getColumnOrder () { checkWidget (); - if (hwndHeader is null) return new int [0]; - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - int [] order = new int [count]; - OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr); + if (columnCount is 0) return null; + int [] order = new int [columnCount]; + OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr); return order; } @@ -2999,10 +3104,8 @@ */ public TreeColumn [] getColumns () { checkWidget (); - if (hwndHeader is null) return new TreeColumn [0]; - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - TreeColumn [] result = new TreeColumn [count]; - System.arraycopy (columns, 0, result, 0, count); + TreeColumn [] result = new TreeColumn [columnCount]; + System.arraycopy (columns, 0, result, 0, columnCount); return result; } @@ -3086,9 +3189,18 @@ lpht.pt.y = point.y; OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); if (lpht.hItem !is null) { - if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & OS.TVHT_ONITEM) !is 0) { - return _getItem (lpht.hItem); - } + int flags = OS.TVHT_ONITEM; + if ((style & DWT.FULL_SELECTION) !is 0) { + flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT; + } else { + if (hooks (DWT.MeasureItem)) { + lpht.flags &= ~(OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL); + if (hitTestSelection ( lpht.hItem, lpht.pt.x, lpht.pt.y)) { + lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL; + } + } + } + if ((lpht.flags & flags) !is 0) return _getItem (lpht.hItem); } return null; } @@ -3328,8 +3440,8 @@ } int count = 0; TreeItem [] guess = new TreeItem [(style & DWT.VIRTUAL) !is 0 ? 8 : 1]; - int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); - OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); + int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc); if ((style & DWT.VIRTUAL) !is 0) { TVITEM tvItem; tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE; @@ -3360,7 +3472,7 @@ } } } - OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc); if (count is 0) return new TreeItem [0]; if (count is guess.length) return guess; TreeItem [] result = new TreeItem [count]; @@ -3368,7 +3480,7 @@ System.arraycopy (guess, 0, result, 0, count); return result; } - OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc); TVITEM tvItem; tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_PARAM | OS.TVIF_STATE; HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); @@ -3377,7 +3489,7 @@ if (count !is getSelection (hItem, &tvItem, result, 0, count, bigSelection, false)) { getSelection (hItem, &tvItem, result, 0, count, bigSelection, true); } - OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc); return result; } @@ -3409,14 +3521,14 @@ return (state & OS.TVIS_SELECTED) is 0 ? 0 : 1; } int count = 0; - int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); + int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC); TVITEM tvItem_; TVITEM* tvItem = null; static if (OS.IsWinCE) { tvItem = &tvitem_; tvItem.mask = OS.TVIF_STATE; } - OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc); if ((style & DWT.VIRTUAL) !is 0) { HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); count = getSelection (hItem, tvItem, null, 0, -1, false, true); @@ -3437,7 +3549,7 @@ } } } - OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc); return count; } @@ -3520,6 +3632,30 @@ return hItem !is null ? _getItem (hItem) : null; } +bool hitTestSelection (HANDLE hItem, int x, int y) { + if (hItem is null) return false; + TreeItem item = _getItem (hItem); + if (item is null) return false; + if (!hooks (DWT.MeasureItem)) return false; + bool result = false; + + //BUG? - moved columns, only hittest first column + //BUG? - check drag detect + int [] order = new int [1], index = new int [1]; + + auto hDC = OS.GetDC (handle); + HFONT oldFont, newFont = cast(HFONT)OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); + if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont); + auto hFont = item.fontHandle (order [index [0]]); + if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); + Event event = sendMeasureItemEvent (item, order [index [0]], hDC); + if (event.getBounds ().contains (x, y)) result = true; + if (newFont !is null) OS.SelectObject (hDC, oldFont); + OS.ReleaseDC (handle, hDC); +// if (isDisposed () || item.isDisposed ()) return false; + return result; +} + int imageIndex (Image image, int index) { if (image is null) return OS.I_IMAGENONE; if (imageList is null) { @@ -3529,6 +3665,11 @@ int imageIndex = imageList.indexOf (image); if (imageIndex is -1) imageIndex = imageList.add (image); if (hwndHeader is null || OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0) is index) { + /* + * Feature in Windows. When setting the same image list multiple + * times, Windows does work making this operation slow. The fix + * is to test for the same image list before setting the new one. + */ auto hImageList = imageList.getHandle (); auto hOldImageList = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0); if (hOldImageList !is hImageList) { @@ -3581,9 +3722,7 @@ checkWidget (); if (column is null) error (DWT.ERROR_NULL_ARGUMENT); if (column.isDisposed()) error(DWT.ERROR_INVALID_ARGUMENT); - if (hwndHeader is null) return -1; - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - for (int i=0; i + *
        • ERROR_NULL_ARGUMENT - if the item is null
        • + *
        • ERROR_INVALID_ARGUMENT - if the item has been disposed
        • + *
        + * @exception DWTException
          + *
        • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
        • + *
        • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
        • + *
        + * + * @since 3.4 + */ +public void select (TreeItem item) { + checkWidget (); + if (item is null) error (DWT.ERROR_NULL_ARGUMENT); + if (item.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT); + if ((style & DWT.SINGLE) !is 0) { + auto hItem = item.handle; + int state = 0; + static if (OS.IsWinCE) { + TVITEM tvItem; + tvItem.hItem = hItem; + tvItem.mask = OS.TVIF_STATE; + OS.SendMessage (handle, OS.TVM_GETITEM, 0, cast(int)&tvItem); + state = tvItem.state; + } else { + state = OS.SendMessage (handle, OS.TVM_GETITEMSTATE, cast(int)&hItem, OS.TVIS_SELECTED); + } + if ((state & OS.TVIS_SELECTED) !is 0) return; + /* + * Feature in Windows. When an item is selected with + * TVM_SELECTITEM and TVGN_CARET, the tree expands and + * scrolls to show the new selected item. Unfortunately, + * there is no other way in Windows to set the focus + * and select an item. The fix is to save the current + * scroll bar positions, turn off redraw, select the item, + * then scroll back to the original position and redraw + * the entire tree. + */ + SCROLLINFO* hInfo = null; + int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); + if ((bits & (OS.TVS_NOHSCROLL | OS.TVS_NOSCROLL)) is 0) { + hInfo = new SCROLLINFO (); + hInfo.cbSize = SCROLLINFO.sizeof; + hInfo.fMask = OS.SIF_ALL; + OS.GetScrollInfo (handle, OS.SB_HORZ, hInfo); + } + SCROLLINFO vInfo; + vInfo.cbSize = SCROLLINFO.sizeof; + vInfo.fMask = OS.SIF_ALL; + OS.GetScrollInfo (handle, OS.SB_VERT, &vInfo); + bool redraw = drawCount is 0 && OS.IsWindowVisible (handle); + if (redraw) { + OS.UpdateWindow (handle); + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); + } + setSelection (item); + if (hInfo !is null) { + int /*long*/ hThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, hInfo.nPos); + OS.SendMessage (handle, OS.WM_HSCROLL, hThumb, 0); + } + int /*long*/ vThumb = OS.MAKELPARAM (OS.SB_THUMBPOSITION, vInfo.nPos); + OS.SendMessage (handle, OS.WM_VSCROLL, vThumb, 0); + if (redraw) { + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); + OS.InvalidateRect (handle, null, true); + if ((style & DWT.DOUBLE_BUFFERED) is 0) { + int oldStyle = style; + style |= DWT.DOUBLE_BUFFERED; + OS.UpdateWindow (handle); + style = oldStyle; + } + } + return; + } + TVITEM tvItem; + tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; + tvItem.stateMask = OS.TVIS_SELECTED; + tvItem.state = OS.TVIS_SELECTED; + tvItem.hItem = item.handle; + OS.SendMessage (handle, OS.TVM_SETITEM, 0, cast(int)&tvItem); +} + +/** * Selects all of the items in the receiver. *

        * If the receiver is single-select, do nothing. @@ -4085,8 +4329,8 @@ tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; tvItem.state = OS.TVIS_SELECTED; tvItem.stateMask = OS.TVIS_SELECTED; - int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); - OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); + int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc); if ((style & DWT.VIRTUAL) !is 0) { HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); select (hItem, &tvItem); @@ -4099,7 +4343,95 @@ } } } - OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc); +} + +Event sendEraseItemEvent (TreeItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* cellRect) { + int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc); + RECT* insetRect = toolTipInset (cellRect); + OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null); + GCData data = new GCData (); + data.device = display; + data.foreground = OS.GetTextColor (nmcd.nmcd.hdc); + data.background = OS.GetBkColor (nmcd.nmcd.hdc); + data.font = item.getFont (column); + data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); + GC gc = GC.win32_new (nmcd.nmcd.hdc, data); + Event event = new Event (); + event.item = item; + event.index = column; + event.gc = gc; + event.detail |= DWT.FOREGROUND; + event.x = cellRect.left; + event.y = cellRect.top; + event.width = cellRect.right - cellRect.left; + event.height = cellRect.bottom - cellRect.top; + //gc.setClipping (event.x, event.y, event.width, event.height); + sendEvent (DWT.EraseItem, event); + event.gc = null; + //int newTextClr = data.foreground; + gc.dispose (); + OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC); + return event; +} + +Event sendMeasureItemEvent (TreeItem item, int index, HDC hDC) { + RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC); + int nSavedDC = OS.SaveDC (hDC); + GCData data = new GCData (); + data.device = display; + data.font = item.getFont (index); + GC gc = GC.win32_new (hDC, data); + Event event = new Event (); + event.item = item; + event.gc = gc; + event.index = index; + event.x = itemRect.left; + event.y = itemRect.top; + event.width = itemRect.right - itemRect.left; + event.height = itemRect.bottom - itemRect.top; + sendEvent (DWT.MeasureItem, event); + event.gc = null; + gc.dispose (); + OS.RestoreDC (hDC, nSavedDC); + if (isDisposed () || item.isDisposed ()) return null; + if (hwndHeader !is null) { + if (columnCount is 0) { + if (event.x + event.width > scrollWidth) { + setScrollWidth (scrollWidth = event.x + event.width); + } + } + } + if (event.height > getItemHeight ()) setItemHeight (event.height); + return event; +} + +Event sendPaintItemEvent (TreeItem item, NMTTCUSTOMDRAW* nmcd, int column, RECT* itemRect) { + int nSavedDC = OS.SaveDC (nmcd.nmcd.hdc); + RECT* insetRect = toolTipInset (itemRect); + OS.SetWindowOrgEx (nmcd.nmcd.hdc, insetRect.left, insetRect.top, null); + GCData data = new GCData (); + data.device = display; + data.font = item.getFont (column); + data.foreground = OS.GetTextColor (nmcd.nmcd.hdc); + data.background = OS.GetBkColor (nmcd.nmcd.hdc); + data.uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); + GC gc = GC.win32_new (nmcd.nmcd.hdc, data); + Event event = new Event (); + event.item = item; + event.index = column; + event.gc = gc; + event.detail |= DWT.FOREGROUND; + event.x = itemRect.left; + event.y = itemRect.top; + event.width = itemRect.right - itemRect.left; + event.height = itemRect.bottom - itemRect.top; + //gc.setClipping (cellRect.left, cellRect.top, cellWidth, cellHeight); + sendEvent (DWT.PaintItem, event); + event.gc = null; + gc.dispose (); + OS.RestoreDC (nmcd.nmcd.hdc, nSavedDC); + return event; } override void setBackgroundImage (HBITMAP hBitmap) { @@ -4164,24 +4496,6 @@ updateFullSelection (); } -override void setBounds (int x, int y, int width, int height, int flags) { - /* - * Ensure that the selection is visible when the tree is resized - * from a zero size to a size that can show the selection. - */ - bool fixSelection = false; - if ((flags & OS.SWP_NOSIZE) is 0 && (width !is 0 || height !is 0)) { - if (OS.SendMessage (handle, OS.TVM_GETVISIBLECOUNT, 0, 0) is 0) { - fixSelection = true; - } - } - super.setBounds (x, y, width, height, flags); - if (fixSelection) { - HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); - if (hItem !is null) showItem (hItem); - } -} - override void setCursor () { /* * Bug in Windows. Under certain circumstances, when WM_SETCURSOR @@ -4224,39 +4538,35 @@ public void setColumnOrder (int [] order) { checkWidget (); if (order is null) error (DWT.ERROR_NULL_ARGUMENT); - int count = 0; - if (hwndHeader !is null) { - count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - } - if (count is 0) { + if (columnCount is 0) { if (order.length !is 0) error (DWT.ERROR_INVALID_ARGUMENT); return; } - if (order.length !is count) error (DWT.ERROR_INVALID_ARGUMENT); - int [] oldOrder = new int [count]; - OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, oldOrder.ptr); + if (order.length !is columnCount) error (DWT.ERROR_INVALID_ARGUMENT); + int [] oldOrder = new int [columnCount]; + OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, oldOrder.ptr); bool reorder = false; - bool [] seen = new bool [count]; + bool [] seen = new bool [columnCount]; for (int i=0; i= count) error (DWT.ERROR_INVALID_RANGE); + if (index < 0 || index >= columnCount) error (DWT.ERROR_INVALID_RANGE); if (seen [index]) error (DWT.ERROR_INVALID_ARGUMENT); seen [index] = true; if (index !is oldOrder [i]) reorder = true; } if (reorder) { - RECT [] oldRects = new RECT [count]; - for (int i=0; i rect.right; - } - if (scroll) { - SCROLLINFO info; - info.cbSize = SCROLLINFO.sizeof; - info.fMask = OS.SIF_POS; - info.nPos = Math.max (0, headerRect.left - Tree.INSET / 2); - OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true); - setScrollWidth (); - } + if (0 <= index && index < columnCount) { + forceResize (); + RECT rect; + OS.GetClientRect (hwndParent, &rect); + OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2); + RECT headerRect; + OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, &headerRect); + bool scroll = headerRect.left < rect.left; + if (!scroll) { + int width = Math.min (rect.right - rect.left, headerRect.right - headerRect.left); + scroll = headerRect.left + width > rect.right; + } + if (scroll) { + SCROLLINFO info; + info.cbSize = SCROLLINFO.sizeof; + info.fMask = OS.SIF_POS; + info.nPos = Math.max (0, headerRect.left - Tree.INSET / 2); + OS.SetScrollInfo (hwndParent, OS.SB_HORZ, &info, true); + setScrollWidth (); } } } @@ -4993,8 +5299,8 @@ } if ((state & OS.TVIS_SELECTED) is 0) return; } else { - int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); - OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); + int /*long*/ oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc); TVITEM tvItem_; TVITEM* tvItem; static if (OS.IsWinCE) { @@ -5026,7 +5332,7 @@ index++; } } - OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc); } if (hItem !is null) showItem (hItem); } @@ -5061,71 +5367,64 @@ override void subclass () { super.subclass (); if (hwndHeader !is null) { - OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, display.windowProc); - } + OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, display.windowProc); + } +} + +RECT* toolTipInset (RECT* rect) { + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + RECT* insetRect = new RECT(); + OS.SetRect (insetRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1); + return insetRect; + } + return rect; +} + +RECT* toolTipRect (RECT* rect) { + RECT* toolRect = new RECT (); + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + OS.SetRect (toolRect, rect.left - 1, rect.top - 1, rect.right + 1, rect.bottom + 1); + } else { + OS.SetRect (toolRect, rect.left, rect.top, rect.right, rect.bottom); + int dwStyle = OS.GetWindowLong (itemToolTipHandle, OS.GWL_STYLE); + int dwExStyle = OS.GetWindowLong (itemToolTipHandle, OS.GWL_EXSTYLE); + OS.AdjustWindowRectEx (toolRect, dwStyle, false, dwExStyle); + } + return toolRect; } override String toolTipText (NMTTDISPINFO* hdr) { auto hwndToolTip = cast(HWND) OS.SendMessage (handle, OS.TVM_GETTOOLTIPS, 0, 0); if (hwndToolTip is hdr.hdr.hwndFrom && toolTipText_ !is null) return ""; //$NON-NLS-1$ if (headerToolTipHandle is hdr.hdr.hwndFrom) { - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - for (int i=0; i> 16); - OS.ScreenToClient (handle, &pt); - TVHITTESTINFO lpht; - lpht.pt.x = pt.x; - lpht.pt.y = pt.y; - OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); - if (lpht.hItem !is null) { - auto hDC = OS.GetDC (handle); - HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); - if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont); - RECT rect; - OS.GetClientRect (hwndParent, &rect); - OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2); - TreeItem item = _getItem (lpht.hItem); - String text = null; - int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0)); - int [] order = new int [count]; - OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr); - while (index < count) { - HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = item.font; - if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); - RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC); - if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); - if (cellRect.left > rect.right) break; - cellRect.right = Math.min (cellRect.right, rect.right); - if (OS.PtInRect (&cellRect, pt)) { - RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC); - if (textRect.right > cellRect.right) { - if (order [index] is 0) { - text = item.text; - } else { - String[] strings = item.strings; - if (strings !is null) text = strings [order [index]]; - } - } - break; - } - index++; - } - if (newFont !is null) OS.SelectObject (hDC, oldFont); - OS.ReleaseDC (handle, hDC); - if (text !is null) return text; - } + int pos = OS.GetMessagePos (); + POINT pt; + OS.POINTSTOPOINT (pt, pos); + OS.ScreenToClient (handle, &pt); + int index; + TreeItem item; + RECT cellRect, itemRect; + if (findCell (pt.x, pt.y, item, index, cellRect, itemRect)) { + String text = null; + if (index is 0) { + text = item.text; + } else { + String[] strings = item.strings; + if (strings !is null) text = strings [index]; + } + //TEMPORARY CODE + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + if (isCustomToolTip ()) text = " "; + } + if (text !is null) return text; } } return super.toolTipText (hdr); @@ -5164,8 +5463,7 @@ lpti.uFlags = OS.TTF_SUBCLASS; lpti.hwnd = hwndHeader; lpti.lpszText = OS.LPSTR_TEXTCALLBACK; - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - for (int i=0; i= OS.VERSION(4, 10)) { + if (info.nPage is 0) { + SCROLLBARINFO psbi; + psbi.cbSize = SCROLLBARINFO.sizeof; + OS.GetScrollBarInfo (handle, OS.OBJID_VSCROLL, &psbi); + if ((psbi.rgstate [0] & OS.STATE_SYSTEM_INVISIBLE) !is 0) { + info.nPage = info.nMax + 1; + } + } + } OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true); } } @@ -5246,13 +5552,13 @@ override void unsubclass () { super.unsubclass (); if (hwndHeader !is null) { - OS.SetWindowLong (hwndHeader, OS.GWL_WNDPROC, cast(int) HeaderProc); + OS.SetWindowLongPtr (hwndHeader, OS.GWLP_WNDPROC, cast(LONG_PTR)HeaderProc); } } override int widgetStyle () { int bits = super.widgetStyle () | OS.TVS_SHOWSELALWAYS | OS.TVS_LINESATROOT | OS.TVS_HASBUTTONS | OS.TVS_NONEVENHEIGHT; - if (EXPLORER_THEME && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { + if (EXPLORER_THEME && !OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0) && OS.IsAppThemed ()) { bits |= OS.TVS_TRACKSELECT; if ((style & DWT.FULL_SELECTION) !is 0) bits |= OS.TVS_FULLROWSELECT; } else { @@ -5262,6 +5568,15 @@ bits |= OS.TVS_HASLINES; } } + if ((style & (DWT.H_SCROLL | DWT.V_SCROLL)) is 0) { + bits &= ~(OS.WS_HSCROLL | OS.WS_VSCROLL); + bits |= OS.TVS_NOSCROLL; + } else { + if ((style & DWT.H_SCROLL) is 0) { + bits &= ~OS.WS_HSCROLL; + bits |= OS.TVS_NOHSCROLL; + } + } // bits |= OS.TVS_NOTOOLTIPS | OS.TVS_DISABLEDRAGDROP; return bits | OS.TVS_DISABLEDRAGDROP; } @@ -5331,17 +5646,15 @@ } case OS.WM_SETCURSOR: { if (cast(HWND)wParam is hwnd) { - int hitTest = cast(short) (lParam & 0xFFFF); + int hitTest = cast(short) OS.LOWORD (lParam); if (hitTest is OS.HTCLIENT) { HDHITTESTINFO pinfo; int pos = OS.GetMessagePos (); POINT pt; - pt.x = cast(short) (pos & 0xFFFF); - pt.y = cast(short) (pos >> 16); + OS.POINTSTOPOINT (pt, pos); OS.ScreenToClient (hwnd, &pt); pinfo.pt.x = pt.x; pinfo.pt.y = pt.y; - int columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); int index = OS.SendMessage (hwndHeader, OS.HDM_HITTEST, 0, &pinfo); if (0 <= index && index < columnCount && !columns [index].resizable) { if ((pinfo.flags & (OS.HHT_ONDIVIDER | OS.HHT_ONDIVOPEN)) !is 0) { @@ -5367,7 +5680,7 @@ setScrollWidth (); if (ignoreResize) return 0; setResizeChildren (false); - int code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam); + int /*long*/ code = callWindowProc (hwnd, OS.WM_SIZE, wParam, lParam); sendEvent (DWT.Resize); if (isDisposed ()) return 0; if (layout_ !is null) { @@ -5421,12 +5734,12 @@ * on Windows Vista. */ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { - if ((wParam & 0xFFFF) is OS.SB_THUMBTRACK) { + if (OS.LOWORD (wParam) is OS.SB_THUMBTRACK) { info.nPos = info.nTrackPos; } } OS.SetScrollInfo (handle, OS.SB_VERT, &info, true); - int code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam); + int /*long*/ code = OS.SendMessage (handle, OS.WM_VSCROLL, wParam, lParam); OS.GetScrollInfo (handle, OS.SB_VERT, &info); OS.SetScrollInfo (hwndParent, OS.SB_VERT, &info, true); return code; @@ -5435,6 +5748,20 @@ } return callWindowProc (hwnd, msg, wParam, lParam); } + if (msg is Display.DI_GETDRAGIMAGE) { + //TEMPORARY CODE + if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) return 0; + /* + * When there is more than one item selected, DI_GETDRAGIMAGE + * returns the item under the cursor. This happens because + * the tree does not have implement multi-select. The fix + * is to disable DI_GETDRAGIMAGE when more than one item is + * selected. + */ + if ((style & DWT.MULTI) !is 0) { + if (getSelectionCount () !is 1) return 0; + } + } return super.windowProc (hwnd, msg, wParam, lParam); } @@ -5545,7 +5872,29 @@ return super.WM_GETOBJECT (wParam, lParam); } -override LRESULT WM_KEYDOWN (int wParam, int lParam) { +override LRESULT WM_HSCROLL (int wParam, int lParam) { + bool fixScroll = false; + if ((style & DWT.DOUBLE_BUFFERED) !is 0) { + fixScroll = (style & DWT.VIRTUAL) !is 0 || hooks (DWT.EraseItem) || hooks (DWT.PaintItem); + } + if (fixScroll) { + style &= ~DWT.DOUBLE_BUFFERED; + if (explorerTheme) { + OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, 0); + } + } + LRESULT result = super.WM_HSCROLL (wParam, lParam); + if (fixScroll) { + style |= DWT.DOUBLE_BUFFERED; + if (explorerTheme) { + OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, OS.TVS_EX_DOUBLEBUFFER); + } + } + if (result !is null) return result; + return result; +} + +override LRESULT WM_KEYDOWN (int /*long*/ wParam, int /*long*/ lParam) { LRESULT result = super.WM_KEYDOWN (wParam, lParam); if (result !is null) return result; switch (wParam) { @@ -5560,10 +5909,9 @@ case OS.VK_ADD: if (OS.GetKeyState (OS.VK_CONTROL) < 0) { if (hwndHeader !is null) { - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - TreeColumn [] newColumns = new TreeColumn [count]; - System.arraycopy (columns, 0, newColumns, 0, count); - for (int i=0; i clientRect.bottom) break; if ((hNewItem = hVisible) is hItem) { OS.SendMessage (handle, OS.WM_VSCROLL, OS.SB_PAGEDOWN, 0); @@ -5701,12 +6047,11 @@ } if (redraw) { RECT rect1, rect2; - rect1.left = cast(int) hItem; rect2.left = cast(int) hNewItem; - int fItemRect = (style & DWT.FULL_SELECTION) !is 0 ? 0 : 1; - if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = 0; - if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = 0; - OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect1); - OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect2); + bool fItemRect = (style & DWT.FULL_SELECTION) is 0; + if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = false; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false; + OS.TreeView_GetItemRect (handle, hItem, &rect1, fItemRect); + OS.TreeView_GetItemRect (handle, hNewItem, &rect2, fItemRect); OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); OS.InvalidateRect (handle, &rect1, true); OS.InvalidateRect (handle, &rect2, true); @@ -5716,7 +6061,7 @@ } } } - int code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_KEYDOWN, wParam, lParam); hAnchor = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); return new LRESULT (code); } @@ -5757,8 +6102,8 @@ override LRESULT WM_LBUTTONDBLCLK (int wParam, int lParam) { TVHITTESTINFO lpht; - lpht.pt.x = cast(short) (lParam & 0xFFFF); - lpht.pt.y = cast(short) (lParam >> 16); + lpht.pt.x = OS.GET_X_LPARAM (lParam); + lpht.pt.y = OS.GET_Y_LPARAM (lParam); OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); if (lpht.hItem !is null) { if ((style & DWT.CHECK) !is 0) { @@ -5807,7 +6152,18 @@ LRESULT result = super.WM_LBUTTONDBLCLK (wParam, lParam); if (result is LRESULT.ZERO) return result; if (lpht.hItem !is null) { - if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & OS.TVHT_ONITEM) !is 0) { + int flags = OS.TVHT_ONITEM; + if ((style & DWT.FULL_SELECTION) !is 0) { + flags |= OS.TVHT_ONITEMRIGHT | OS.TVHT_ONITEMINDENT; + } else { + if (hooks (DWT.MeasureItem)) { + lpht.flags &= ~(OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL); + if (hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y)) { + lpht.flags |= OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL; + } + } + } + if ((lpht.flags & flags) !is 0) { Event event = new Event (); event.item = _getItem (lpht.hItem); postEvent (DWT.DefaultSelection, event); @@ -5825,8 +6181,8 @@ * below the last item is selected. */ TVHITTESTINFO lpht; - lpht.pt.x = cast(short) (lParam & 0xFFFF); - lpht.pt.y = cast(short) (lParam >> 16); + lpht.pt.x = OS.GET_X_LPARAM (lParam); + lpht.pt.y = OS.GET_Y_LPARAM (lParam); OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); if (lpht.hItem is null || (lpht.flags & OS.TVHT_ONITEMBUTTON) !is 0) { Display display = this.display; @@ -5838,9 +6194,9 @@ return LRESULT.ZERO; } bool fixSelection = false, deselected = false; + HANDLE hOldSelection = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); if (lpht.hItem !is null && (style & DWT.MULTI) !is 0) { - int hSelection = OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); - if (hSelection !is 0) { + if (hOldSelection !is null) { TVITEM tvItem; tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; tvItem.hItem = lpht.hItem; @@ -5850,6 +6206,7 @@ tvItem.stateMask = OS.TVIS_SELECTED; auto hNext = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, lpht.hItem); while (hNext !is null) { + if (hNext is hAnchor) hAnchor = null; tvItem.hItem = hNext; OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem); if ((tvItem.state & OS.TVIS_SELECTED) !is 0) deselected = true; @@ -5866,13 +6223,39 @@ } dragStarted = gestureCompleted = false; if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = true; - int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); if (fixSelection) ignoreDeselect = ignoreSelect = lockSelection = false; + HANDLE hNewSelection = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); + if (hOldSelection !is hNewSelection) hAnchor = hNewSelection; if (dragStarted) { if (!display.captureChanged && !isDisposed ()) { if (OS.GetCapture () !is handle) OS.SetCapture (handle); } } + /* + * Bug in Windows. When a tree has no images and an item is + * expanded or collapsed, for some reason, Windows changes + * the size of the selection. When the user expands a tree + * item, the selection rectangle is made a few pixels larger. + * When the user collapses an item, the selection rectangle + * is restored to the original size but the selection is not + * redrawn, causing pixel corruption. The fix is to detect + * this case and redraw the item. + */ + if ((lpht.flags & OS.TVHT_ONITEMBUTTON) !is 0) { + int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); + if ((bits & OS.TVS_FULLROWSELECT) is 0) { + if (OS.SendMessage (handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0) is 0) { + auto hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); + if (hItem !is null) { + RECT rect; + if (OS.TreeView_GetItemRect (handle, hItem, &rect, false)) { + OS.InvalidateRect (handle, &rect, true); + } + } + } + } + } if (deselected) { Event event = new Event (); event.item = _getItem (lpht.hItem); @@ -5924,8 +6307,31 @@ } } + /* + * Feature in Windows. When the tree has the style + * TVS_FULLROWSELECT, the background color for the + * entire row is filled when an item is painted, + * drawing on top of any custom drawing. The fix + * is to emulate TVS_FULLROWSELECT. + */ + bool selected = false; + bool fakeSelection = false; + if (lpht.hItem !is null) { + if ((style & DWT.FULL_SELECTION) !is 0) { + int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); + if ((bits & OS.TVS_FULLROWSELECT) is 0) fakeSelection = true; + } else { + if (hooks (DWT.MeasureItem)) { + selected = hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y) !is 0; + if (selected) { + if ((lpht.flags & OS.TVHT_ONITEM) is 0) fakeSelection = true; + } + } + } + } + /* Process the mouse when an item is not selected */ - if ((style & DWT.FULL_SELECTION) is 0) { + if (!selected && (style & DWT.FULL_SELECTION) is 0) { if ((lpht.flags & OS.TVHT_ONITEM) is 0) { Display display = this.display; display.captureChanged = false; @@ -5935,7 +6341,7 @@ } return LRESULT.ZERO; } - int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); if (!display.captureChanged && !isDisposed ()) { if (OS.GetCapture () !is handle) OS.SetCapture (handle); } @@ -5947,16 +6353,14 @@ TVITEM tvItem; tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; tvItem.stateMask = OS.TVIS_SELECTED; - bool hittestSelected = false, focused = false; + bool hittestSelected = false; if ((style & DWT.MULTI) !is 0) { tvItem.hItem = lpht.hItem; OS.SendMessage (handle, OS.TVM_GETITEM, 0, &tvItem); hittestSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0; - focused = OS.GetFocus () is handle; } /* Get the selected state of the last selected item */ - bool redraw = false; auto hOldItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); if ((style & DWT.MULTI) !is 0) { tvItem.hItem = hOldItem; @@ -5966,8 +6370,8 @@ if (hittestSelected || (wParam & OS.MK_CONTROL) !is 0) { /* * Feature in Windows. When the tree is not drawing focus - * and the user selects a tree item using while the CONTROL - * key is down, the tree window proc sends WM_UPDATEUISTATE + * and the user selects a tree item while the CONTROL key + * is down, the tree window proc sends WM_UPDATEUISTATE * to the top level window, causing controls within the shell * to redraw. When drag detect is enabled, the tree window * proc runs a modal loop that allows WM_PAINT messages to be @@ -5978,23 +6382,21 @@ * on without redrawing the entire tree, pixel corruption occurs. * This case only seems to happen when the tree has been given * focus from WM_MOUSEACTIVATE of the shell. The fix is to - * detect that WM_UPDATEUISTATE will be sent and avoid using - * WM_SETREDRAW to disable drawing. + * force the WM_UPDATEUISTATE to be sent before disabling + * the drawing. * * NOTE: Any redraw of a parent (or sibling) will be dispatched * during the modal drag detect loop. This code only fixes the * case where the tree causes a redraw from WM_UPDATEUISTATE. - * In DWT, the InvalidateRect() that causes the pixel corruption + * In DWT, the InvalidateRect() that caused the pixel corruption * is found in Composite.WM_UPDATEUISTATE(). */ int uiState = OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - if ((uiState & OS.UISF_HIDEFOCUS) is 0) { - redraw = focused && drawCount is 0 && OS.IsWindowVisible (handle); - } - if (redraw) { - OS.UpdateWindow (handle); - OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); - } + if ((uiState & OS.UISF_HIDEFOCUS) !is 0) { + OS.SendMessage (handle, OS.WM_CHANGEUISTATE, OS.UIS_INITIALIZE, 0); + } + OS.UpdateWindow (handle); + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 0, 0); } else { deselectAll (); } @@ -6012,25 +6414,15 @@ hSelect = lpht.hItem; dragStarted = gestureCompleted = false; ignoreDeselect = ignoreSelect = true; - int code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_LBUTTONDOWN, wParam, lParam); auto hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); - /* - * Feature in Windows. When the tree has the style - * TVS_FULLROWSELECT, the background color for the - * entire row is filled when an item is painted, - * drawing on top of any custom drawing. The fix - * is to emulate TVS_FULLROWSELECT. - */ - if ((style & DWT.FULL_SELECTION) !is 0) { - int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); - if ((bits & OS.TVS_FULLROWSELECT) is 0) { - if (hNewItem is hOldItem && lpht.hItem !is hOldItem) { - OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem); - hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); - } - if (!dragStarted && lpht.hItem !is null && (state & DRAG_DETECT) !is 0 && hooks (DWT.DragDetect)) { - dragStarted = dragDetect (handle, lpht.pt.x, lpht.pt.y, false, null, null); - } + if (fakeSelection) { + if (hOldItem is null || (hNewItem is hOldItem && lpht.hItem !is hOldItem)) { + OS.SendMessage (handle, OS.TVM_SELECTITEM, OS.TVGN_CARET, lpht.hItem); + hNewItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CARET, 0); + } + if (!dragStarted && (state & DRAG_DETECT) !is 0 && hooks (DWT.DragDetect)) { + dragStarted = dragDetect (handle, lpht.pt.x, lpht.pt.y, false, null, null); } } ignoreDeselect = ignoreSelect = false; @@ -6083,27 +6475,24 @@ } } } - if (redraw) { - RECT rect1, rect2; - rect1.left = cast(int) hOldItem; rect2.left = cast(int) hNewItem; - int fItemRect = (style & DWT.FULL_SELECTION) !is 0 ? 0 : 1; - if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = 0; - if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = 0; - OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect1); - OS.SendMessage (handle, OS.TVM_GETITEMRECT, fItemRect, &rect2); - OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); - OS.InvalidateRect (handle, &rect1, true); - OS.InvalidateRect (handle, &rect2, true); - OS.UpdateWindow (handle); - } + RECT rect1, rect2; + bool fItemRect = (style & DWT.FULL_SELECTION) is 0; + if (hooks (DWT.EraseItem) || hooks (DWT.PaintItem)) fItemRect = false; + if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) fItemRect = false; + OS.TreeView_GetItemRect (handle, hOldItem, &rect1, fItemRect); + OS.TreeView_GetItemRect (handle, hNewItem, &rect2, fItemRect); + OS.DefWindowProc (handle, OS.WM_SETREDRAW, 1, 0); + OS.InvalidateRect (handle, &rect1, true); + OS.InvalidateRect (handle, &rect2, true); + OS.UpdateWindow (handle); } /* Check for SHIFT or normal select and deselect/reselect items */ if ((wParam & OS.MK_CONTROL) is 0) { if (!hittestSelected || !dragStarted) { tvItem.state = 0; - int oldProc = OS.GetWindowLong (handle, OS.GWL_WNDPROC); - OS.SetWindowLong (handle, OS.GWL_WNDPROC, cast(int) TreeProc); + auto oldProc = OS.GetWindowLongPtr (handle, OS.GWLP_WNDPROC); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, cast(LONG_PTR)TreeProc); if ((style & DWT.VIRTUAL) !is 0) { HANDLE hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_ROOT, 0); deselect (hItem, &tvItem, hNewItem); @@ -6119,23 +6508,22 @@ tvItem.hItem = hNewItem; tvItem.state = OS.TVIS_SELECTED; OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); - OS.SetWindowLong (handle, OS.GWL_WNDPROC, oldProc); + OS.SetWindowLongPtr (handle, OS.GWLP_WNDPROC, oldProc); if ((wParam & OS.MK_SHIFT) !is 0) { RECT rect1; if (hAnchor is null) hAnchor = hNewItem; - rect1.left = cast(int) hAnchor; - if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect1) !is 0) { + if (OS.TreeView_GetItemRect (handle, hAnchor, &rect1, false)) { RECT rect2; - rect2.left = cast(int) hNewItem; - OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect2); - int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE; - tvItem.state = OS.TVIS_SELECTED; - auto hItem = tvItem.hItem = hAnchor; - OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); - while (hItem !is hNewItem) { - tvItem.hItem = hItem; + if (OS.TreeView_GetItemRect (handle, hNewItem, &rect2, false)) { + int flags = rect1.top < rect2.top ? OS.TVGN_NEXTVISIBLE : OS.TVGN_PREVIOUSVISIBLE; + tvItem.state = OS.TVIS_SELECTED; + auto hItem = tvItem.hItem = hAnchor; OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); - hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem); + while (hItem !is hNewItem) { + tvItem.hItem = hItem; + OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); + hItem = cast(HANDLE) OS.SendMessage (handle, OS.TVM_GETNEXTITEM, flags, hItem); + } } } } @@ -6164,7 +6552,7 @@ * issue a fake mouse up. */ if (dragStarted) { - sendDragEvent (1, cast(short) (lParam & 0xFFFF), cast(short) (lParam >> 16)); + sendDragEvent (1, OS.GET_X_LPARAM (lParam), OS.GET_Y_LPARAM (lParam)); } else { int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); if ((bits & OS.TVS_DISABLEDRAGDROP) is 0) { @@ -6179,7 +6567,7 @@ Display display = this.display; LRESULT result = super.WM_MOUSEMOVE (wParam, lParam); if (result !is null) return result; - if (itemToolTipHandle !is null && hwndHeader !is null) { + if (itemToolTipHandle !is null) { /* * Bug in Windows. On some machines that do not have XBUTTONs, * the MK_XBUTTON1 and OS.MK_XBUTTON2 bits are sometimes set, @@ -6188,53 +6576,36 @@ */ int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON; if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2; - if (((wParam & 0xFFFF) & mask) is 0) { - TVHITTESTINFO lpht; - lpht.pt.x = cast(short) (lParam & 0xFFFF); - lpht.pt.y = cast(short) (lParam >> 16); - OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); - if (lpht.hItem !is null) { - auto hDC = OS.GetDC (handle); - HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); - if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont); - POINT pt; - pt.x = lpht.pt.x; - pt.y = lpht.pt.y; - RECT rect; - OS.GetClientRect (hwndParent, &rect); - OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2); - TreeItem item = _getItem (lpht.hItem); - int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0)); - int [] order = new int [count]; - OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr); - while (index < count) { - HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = item.font; - if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); - RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC); - if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); - if (cellRect.left > rect.right) break; - cellRect.right = Math.min (cellRect.right, rect.right); - if (OS.PtInRect (&cellRect, pt)) { - RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC); - if (textRect.right > cellRect.right) { - TOOLINFO lpti; - lpti.cbSize = TOOLINFO.sizeof; - lpti.hwnd = handle; - lpti.uId = cast(int) handle; - lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT; - lpti.rect.left = cellRect.left; - lpti.rect.top = cellRect.top; - lpti.rect.right = cellRect.right; - lpti.rect.bottom = cellRect.bottom; - OS.SendMessage (itemToolTipHandle, OS.TTM_NEWTOOLRECT, 0, &lpti); - } - break; + if ((wParam & mask) is 0) { + int x = OS.GET_X_LPARAM (lParam); + int y = OS.GET_Y_LPARAM (lParam); + int index; + TreeItem item; + RECT cellRect, itemRect; + if (findCell (x, y, item, index, cellRect, itemRect)) { + /* + * Feature in Windows. When the new tool rectangle is + * set using TTM_NEWTOOLRECT and the tooltip is visible, + * Windows draws the tooltip right away and the sends + * WM_NOTIFY with TTN_SHOW. This means that the tooltip + * shows first at the wrong location and then moves to + * the right one. The fix is to hide the tooltip window. + */ + if (OS.SendMessage (itemToolTipHandle, OS.TTM_GETCURRENTTOOL, 0, 0) is 0) { + if (OS.IsWindowVisible (itemToolTipHandle)) { + OS.ShowWindow (itemToolTipHandle, OS.SW_HIDE); } - index++; } - if (newFont !is null) OS.SelectObject (hDC, oldFont); - OS.ReleaseDC (handle, hDC); + TOOLINFO lpti; + lpti.cbSize = TOOLINFO.sizeof; + lpti.hwnd = handle; + lpti.uId = cast(int) handle; + lpti.uFlags = OS.TTF_SUBCLASS | OS.TTF_TRANSPARENT; + lpti.rect.left = cellRect.left; + lpti.rect.top = cellRect.top; + lpti.rect.right = cellRect.right; + lpti.rect.bottom = cellRect.bottom; + OS.SendMessage (itemToolTipHandle, OS.TTM_NEWTOOLRECT, 0, &lpti); } } } @@ -6283,12 +6654,20 @@ * This behavior is consistent with the table. */ TVHITTESTINFO lpht; - lpht.pt.x = cast(short) (lParam & 0xFFFF); - lpht.pt.y = cast(short) (lParam >> 16); + lpht.pt.x = OS.GET_X_LPARAM (lParam); + lpht.pt.y = OS.GET_Y_LPARAM (lParam); OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); if (lpht.hItem !is null) { - int flags = OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL; - if ((style & DWT.FULL_SELECTION) !is 0 || (lpht.flags & flags) !is 0) { + bool fakeSelection = (style & DWT.FULL_SELECTION) !is 0; + if (!fakeSelection) { + if (hooks (DWT.MeasureItem)) { + fakeSelection = hitTestSelection (lpht.hItem, lpht.pt.x, lpht.pt.y); + } else { + int flags = OS.TVHT_ONITEMICON | OS.TVHT_ONITEMLABEL; + fakeSelection = (lpht.flags & flags) !is 0; + } + } + if (fakeSelection) { if ((wParam & (OS.MK_CONTROL | OS.MK_SHIFT)) is 0) { TVITEM tvItem; tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE; @@ -6326,11 +6705,9 @@ } if ((style & DWT.DOUBLE_BUFFERED) !is 0 || findImageControl () !is null) { bool doubleBuffer = true; - if (EXPLORER_THEME) { - if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { - int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0); - if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) doubleBuffer = false; - } + if (explorerTheme) { + int exStyle = OS.SendMessage (handle, OS.TVM_GETEXTENDEDSTYLE, 0, 0); + if ((exStyle & OS.TVS_EX_DOUBLEBUFFER) !is 0) doubleBuffer = false; } if (doubleBuffer) { GC gc = null; @@ -6402,7 +6779,7 @@ * is happening in WM_PRINTCLIENT, the redrawing is not visible. */ printClient = true; - int code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam); + int /*long*/ code = callWindowProc (handle, OS.WM_PRINTCLIENT, wParam, lParam); printClient = false; return new LRESULT (code); } @@ -6475,7 +6852,7 @@ * Windows Vista running under the theme manager. */ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { - int code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam); + int /*long*/ code = OS.DefWindowProc (handle, OS.WM_SETREDRAW, wParam, lParam); return code is 0 ? LRESULT.ZERO : new LRESULT (code); } return result; @@ -6499,12 +6876,8 @@ * of the selected items is not drawn. The fix is the * redraw the entire tree. */ - if (EXPLORER_THEME) { - if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION (6, 0)) { - if ((style & DWT.FULL_SELECTION) !is 0) { - OS.InvalidateRect (handle, null, false); - } - } + if (explorerTheme && (style & DWT.FULL_SELECTION) !is 0) { + OS.InvalidateRect (handle, null, false); } if (ignoreResize) return null; return super.WM_SIZE (wParam, lParam); @@ -6526,6 +6899,38 @@ return result; } +override LRESULT WM_VSCROLL (int /*long*/ wParam, int /*long*/ lParam) { + bool fixScroll = false; + if ((style & DWT.DOUBLE_BUFFERED) !is 0) { + int code = OS.LOWORD (wParam); + switch (code) { + case OS.SB_TOP: + case OS.SB_BOTTOM: + case OS.SB_LINEDOWN: + case OS.SB_LINEUP: + case OS.SB_PAGEDOWN: + case OS.SB_PAGEUP: + fixScroll = (style & DWT.VIRTUAL) !is 0 || hooks (DWT.EraseItem) || hooks (DWT.PaintItem); + break; + } + } + if (fixScroll) { + style &= ~DWT.DOUBLE_BUFFERED; + if (explorerTheme) { + OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, 0); + } + } + LRESULT result = super.WM_VSCROLL (wParam, lParam); + if (fixScroll) { + style |= DWT.DOUBLE_BUFFERED; + if (explorerTheme) { + OS.SendMessage (handle, OS.TVM_SETEXTENDEDSTYLE, OS.TVS_EX_DOUBLEBUFFER, OS.TVS_EX_DOUBLEBUFFER); + } + } + if (result !is null) return result; + return result; +} + override LRESULT wmColorChild (int wParam, int lParam) { if (findImageControl () !is null) { if (OS.COMCTL32_MAJOR < 6) { @@ -6544,274 +6949,13 @@ } override LRESULT wmNotify (NMHDR* hdr, int wParam, int lParam) { - if (hdr.hwndFrom is itemToolTipHandle && hwndHeader !is null) { - static if (!OS.IsWinCE) { - switch (hdr.code) { - case OS.TTN_POP: { - if (display.isXMouseActive ()) { - Shell shell = getShell (); - shell.lockToolTipControl = null; - } - break; - } - case OS.TTN_SHOW: { - if (display.isXMouseActive ()) { - Shell shell = getShell (); - shell.lockToolTipControl = this; - } - int pos = OS.GetMessagePos (); - POINT pt; - pt.x = cast(short) (pos & 0xFFFF); - pt.y = cast(short) (pos >> 16); - OS.ScreenToClient (handle, &pt); - TVHITTESTINFO lpht; - lpht.pt.x = pt.x; - lpht.pt.y = pt.y; - OS.SendMessage (handle, OS.TVM_HITTEST, 0, &lpht); - if (lpht.hItem !is null) { - auto hDC = OS.GetDC (handle); - HFONT oldFont, newFont = cast(HFONT) OS.SendMessage (handle, OS.WM_GETFONT, 0, 0); - if (newFont !is null) oldFont = OS.SelectObject (hDC, newFont); - LRESULT result = null; - RECT rect; - OS.GetClientRect (hwndParent, &rect); - OS.MapWindowPoints (hwndParent, handle, cast(POINT*) &rect, 2); - TreeItem item = _getItem (lpht.hItem); - int index = 0, count = Math.max (1, OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0)); - int [] order = new int [count]; - OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr); - while (index < count) { - HFONT hFont = item.cellFont !is null ? item.cellFont [order [index]] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = item.font; - if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); - RECT cellRect = item.getBounds (order [index], true, false, true, false, true, hDC); - if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); - if (cellRect.left > rect.right) break; - cellRect.right = Math.min (cellRect.right, rect.right); - if (OS.PtInRect (&cellRect, pt)) { - RECT textRect = item.getBounds (order [index], true, false, false, false, false, hDC); - if (textRect.right > cellRect.right) { - OS.MapWindowPoints (handle, null, cast(POINT*) &textRect, 2); - int flags = OS.SWP_NOACTIVATE | OS.SWP_NOSIZE | OS.SWP_NOZORDER; - SetWindowPos (itemToolTipHandle, null, textRect.left, textRect.top, 0, 0, flags); - result = LRESULT.ONE; - } - break; - } - index++; - } - if (newFont !is null) OS.SelectObject (hDC, oldFont); - OS.ReleaseDC (handle, hDC); - if (result !is null) return result; - } - } - default: - } - } + if (hdr.hwndFrom is itemToolTipHandle) { + LRESULT result = wmNotifyToolTip (hdr, wParam, lParam); + if (result !is null) return result; } if (hdr.hwndFrom is hwndHeader) { - /* - * Feature in Windows. On NT, the automatically created - * header control is created as a UNICODE window, not an - * ANSI window despite the fact that the parent is created - * as an ANSI window. This means that it sends UNICODE - * notification messages to the parent window on NT for - * no good reason. The data and size in the NMHEADER and - * HDITEM structs is identical between the platforms so no - * different message is actually necessary. Despite this, - * Windows sends different messages. The fix is to look - * for both messages, despite the platform. This works - * because only one will be sent on either platform, never - * both. - */ - switch (hdr.code) { - case OS.HDN_BEGINTRACKW: - case OS.HDN_BEGINTRACKA: - case OS.HDN_DIVIDERDBLCLICKW: - case OS.HDN_DIVIDERDBLCLICKA: { - NMHEADER* phdn = cast(NMHEADER*)lParam; - //OS.MoveMemory (phdn, lParam, NMHEADER.sizeof); - TreeColumn column = columns [phdn.iItem]; - if (column !is null && !column.getResizable ()) { - return LRESULT.ONE; - } - ignoreColumnMove = true; - switch (hdr.code) { - case OS.HDN_DIVIDERDBLCLICKW: - case OS.HDN_DIVIDERDBLCLICKA: - if (column !is null) column.pack (); - default: - } - break; - } - case OS.NM_RELEASEDCAPTURE: { - if (!ignoreColumnMove) { - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - for (int i=0; i= OS.VERSION (6, 0)) { - int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN; - OS.RedrawWindow (handle, null, null, flags); - } else { - if ((style & DWT.DOUBLE_BUFFERED) is 0) { - int oldStyle = style; - style |= DWT.DOUBLE_BUFFERED; - OS.UpdateWindow (handle); - style = oldStyle; - } - } - } - TreeColumn column = columns [phdn.iItem]; - if (column !is null) { - column.updateToolTip (phdn.iItem); - column.sendEvent (DWT.Resize); - if (isDisposed ()) return LRESULT.ZERO; - int count = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); - TreeColumn [] newColumns = new TreeColumn [count]; - System.arraycopy (columns, 0, newColumns, 0, count); - int [] order = new int [count]; - OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, count, order.ptr); - bool moved = false; - for (int i=0; i> 16); + OS.POINTSTOPOINT (pt, pos); OS.ScreenToClient (handle, &pt); TVHITTESTINFO lpht; lpht.pt.x = pt.x; @@ -7028,12 +7171,10 @@ if ((style & DWT.MULTI) !is 0) { if (lockSelection) { /* Save the old selection state for both items */ - TVITEM tvItem; - int offset1 = NMHDR.sizeof + 4; - OS.MoveMemory (&tvItem, lParam + offset1, TVITEM.sizeof); + auto treeView = cast(NMTREEVIEW*)lParam; + TVITEM* tvItem = &treeView.itemOld; oldSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0; - int offset2 = NMHDR.sizeof + 4 + TVITEM.sizeof; - OS.MoveMemory (&tvItem, lParam + offset2, TVITEM.sizeof); + tvItem = &treeView.itemNew; newSelected = (tvItem.state & OS.TVIS_SELECTED) !is 0; } } @@ -7045,22 +7186,25 @@ } case OS.TVN_SELCHANGEDA: case OS.TVN_SELCHANGEDW: { + NMTREEVIEW* treeView = null; if ((style & DWT.MULTI) !is 0) { if (lockSelection) { /* Restore the old selection state of both items */ if (oldSelected) { - TVITEM tvItem; - int offset = NMHDR.sizeof + 4; - OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); + if (treeView is null) { + treeView = cast(NMTREEVIEW*)lParam; + } + TVITEM tvItem = treeView.itemOld; tvItem.mask = OS.TVIF_STATE; tvItem.stateMask = OS.TVIS_SELECTED; tvItem.state = OS.TVIS_SELECTED; OS.SendMessage (handle, OS.TVM_SETITEM, 0, &tvItem); } if (!newSelected && ignoreSelect) { - TVITEM tvItem; - int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; - OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); + if (treeView is null) { + treeView = cast(NMTREEVIEW*)lParam; + } + TVITEM tvItem = treeView.itemNew; tvItem.mask = OS.TVIF_STATE; tvItem.stateMask = OS.TVIS_SELECTED; tvItem.state = 0; @@ -7069,9 +7213,10 @@ } } if (!ignoreSelect) { - TVITEM tvItem; - int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; - OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); + if (treeView is null) { + treeView = cast(NMTREEVIEW*)lParam; + } + TVITEM tvItem = treeView.itemNew; hAnchor = tvItem.hItem; Event event = new Event (); event.item = _getItem (&tvItem.hItem, tvItem.lParam); @@ -7099,9 +7244,9 @@ OS.SendMessage (handle, OS.TVM_SETINSERTMARK, 0, 0); } if (!ignoreExpand) { - TVITEM tvItem; - int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; - OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); + NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam; + + TVITEM* tvItem = &treeView.itemNew; /* * Feature in Windows. In some cases, TVM_ITEMEXPANDING * is sent from within TVM_DELETEITEM for the tree item @@ -7114,9 +7259,7 @@ if (item is null) break; Event event = new Event (); event.item = item; - int action = *cast(int*)(lParam + NMHDR.sizeof); - //OS.MoveMemory (action, lParam + NMHDR.sizeof, 4); - switch (action) { + switch (treeView.action) { case OS.TVE_EXPAND: /* * Bug in Windows. When the numeric keypad asterisk @@ -7176,16 +7319,16 @@ */ if (!OS.IsWinCE && OS.COMCTL32_MAJOR >= 6) { if (imageList !is null) { - TVITEM tvItem; - int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; - OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); + NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam; + + TVITEM* tvItem = &treeView.itemNew; if (tvItem.hItem !is null) { int bits = OS.GetWindowLong (handle, OS.GWL_STYLE); if ((bits & OS.TVS_FULLROWSELECT) is 0) { RECT rect; - rect.left = cast(int)tvItem.hItem; - OS.SendMessage (handle, OS.TVM_GETITEMRECT, 0, &rect); - OS.InvalidateRect (handle, &rect, true); + if (OS.TreeView_GetItemRect (handle, tvItem.hItem, &rect, false)) { + OS.InvalidateRect (handle, &rect, true); + } } } } @@ -7195,11 +7338,13 @@ } case OS.TVN_BEGINDRAGA: case OS.TVN_BEGINDRAGW: + if (OS.GetKeyState (OS.VK_LBUTTON) >= 0) break; + //FALL THROUGH case OS.TVN_BEGINRDRAGA: case OS.TVN_BEGINRDRAGW: { - TVITEM tvItem; - int offset = NMHDR.sizeof + 4 + TVITEM.sizeof; - OS.MoveMemory (&tvItem, lParam + offset, TVITEM.sizeof); + dragStarted = true; + NMTREEVIEW* treeView = cast(NMTREEVIEW*)lParam; + TVITEM* tvItem = &treeView.itemNew; if (tvItem.hItem !is null && (tvItem.state & OS.TVIS_SELECTED) is 0) { hSelect = tvItem.hItem; ignoreSelect = ignoreDeselect = true; @@ -7207,7 +7352,6 @@ ignoreSelect = ignoreDeselect = false; hSelect = null; } - dragStarted = true; break; } case OS.NM_RECOGNIZEGESTURE: { @@ -7244,4 +7388,336 @@ return super.wmNotifyChild (hdr, wParam, lParam); } -} +LRESULT wmNotifyHeader (NMHDR* hdr, int /*long*/ wParam, int /*long*/ lParam) { + /* + * Feature in Windows. On NT, the automatically created + * header control is created as a UNICODE window, not an + * ANSI window despite the fact that the parent is created + * as an ANSI window. This means that it sends UNICODE + * notification messages to the parent window on NT for + * no good reason. The data and size in the NMHEADER and + * HDITEM structs is identical between the platforms so no + * different message is actually necessary. Despite this, + * Windows sends different messages. The fix is to look + * for both messages, despite the platform. This works + * because only one will be sent on either platform, never + * both. + */ + switch (hdr.code) { + case OS.HDN_BEGINTRACKW: + case OS.HDN_BEGINTRACKA: + case OS.HDN_DIVIDERDBLCLICKW: + case OS.HDN_DIVIDERDBLCLICKA: { + NMHEADER* phdn = cast(NMHEADER*)lParam; + TreeColumn column = columns [phdn.iItem]; + if (column !is null && !column.getResizable ()) { + return LRESULT.ONE; + } + ignoreColumnMove = true; + switch (hdr.code) { + case OS.HDN_DIVIDERDBLCLICKW: + case OS.HDN_DIVIDERDBLCLICKA: + if (column !is null) column.pack (); + } + break; + } + case OS.NM_RELEASEDCAPTURE: { + if (!ignoreColumnMove) { + for (int i=0; i= OS.VERSION (6, 0)) { + int flags = OS.RDW_UPDATENOW | OS.RDW_ALLCHILDREN; + OS.RedrawWindow (handle, null, null, flags); + } else { + if ((style & DWT.DOUBLE_BUFFERED) is 0) { + int oldStyle = style; + style |= DWT.DOUBLE_BUFFERED; + OS.UpdateWindow (handle); + style = oldStyle; + } + } + } + TreeColumn column = columns [phdn.iItem]; + if (column !is null) { + column.updateToolTip (phdn.iItem); + column.sendEvent (DWT.Resize); + if (isDisposed ()) return LRESULT.ZERO; + TreeColumn [] newColumns = new TreeColumn [columnCount]; + System.arraycopy (columns, 0, newColumns, 0, columnCount); + int [] order = new int [columnCount]; + OS.SendMessage (hwndHeader, OS.HDM_GETORDERARRAY, columnCount, order.ptr); + bool moved = false; + for (int i=0; i - * + *

        + * Note that due to a restriction on some platforms, the first column + * is always left aligned. + *

        * @param parent a composite control which will be the parent of the new instance (cannot be null) * @param style the style of control to construct * @param index the zero-relative index to store the receiver in its parent @@ -357,35 +358,19 @@ OS.SendMessage (hwnd, OS.TVM_GETITEM, 0, cast(int) &tvItem); TreeItem item = tvItem.lParam !is -1 ? parent.items [tvItem.lParam] : null; if (item !is null) { - auto hFont = item.cellFont !is null ? item.cellFont [index] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = item.font; - if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); - RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC); - if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); + int itemRight = 0; if (parent.hooks (DWT.MeasureItem)) { - auto nSavedDC = OS.SaveDC (hDC); - GCData data = new GCData (); - data.device = display; - data.hFont = hFont; - GC gc = GC.win32_new (hDC, data); - Event event = new Event (); - event.item = item; - event.gc = gc; - event.index = index; - event.x = itemRect.left; - event.y = itemRect.top; - event.width = itemRect.right - itemRect.left; - event.height = itemRect.bottom - itemRect.top; - parent.sendEvent (DWT.MeasureItem, event); - event.gc = null; - gc.dispose (); - OS.RestoreDC (hDC, nSavedDC); + Event event = parent.sendMeasureItemEvent (item, index, hDC); if (isDisposed () || parent.isDisposed ()) break; - if (event.height > parent.getItemHeight ()) parent.setItemHeight (event.height); - //itemRect.left = event.x; - itemRect.right = event.x + event.width; + itemRight = event.x + event.width; + } else { + auto hFont = item.fontHandle (index); + if (hFont !is cast(HFONT)-1) hFont = OS.SelectObject (hDC, hFont); + RECT itemRect = item.getBounds (index, true, true, false, false, false, hDC); + if (hFont !is cast(HFONT)-1) OS.SelectObject (hDC, hFont); + itemRight = itemRect.right; } - columnWidth = Math.max (columnWidth, itemRect.right - headerRect.left); + columnWidth = Math.max (columnWidth, itemRight - headerRect.left); } tvItem.hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, tvItem.hItem); } @@ -490,7 +475,10 @@ * Controls how text and images will be displayed in the receiver. * The argument should be one of LEFT, RIGHT * or CENTER. - * + *

        + * Note that due to a restriction on some platforms, the first column + * is always left aligned. + *

        * @param alignment the new alignment * * @exception DWTException
          @@ -508,7 +496,7 @@ auto hwndHeader = parent.hwndHeader; if (hwndHeader is null) return; HDITEM hdItem; - hdItem.mask = OS.HDI_FORMAT | OS.HDI_IMAGE; + hdItem.mask = OS.HDI_FORMAT; OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, &hdItem); hdItem.fmt &= ~OS.HDF_JUSTIFYMASK; if ((style & DWT.LEFT) is DWT.LEFT) hdItem.fmt |= OS.HDF_LEFT; @@ -623,10 +611,12 @@ case DWT.UP: hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTDOWN); hdItem.fmt |= OS.HDF_SORTUP; + if (image is null) hdItem.mask &= ~OS.HDI_IMAGE; break; case DWT.DOWN: hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTUP); hdItem.fmt |= OS.HDF_SORTDOWN; + if (image is null) hdItem.mask &= ~OS.HDI_IMAGE; break; case DWT.NONE: hdItem.fmt &= ~(OS.HDF_SORTUP | OS.HDF_SORTDOWN); @@ -635,6 +625,7 @@ hdItem.iImage = parent.imageIndexHeader (image); } else { hdItem.fmt &= ~OS.HDF_IMAGE; + hdItem.mask &= ~OS.HDI_IMAGE; } break; default: @@ -681,7 +672,7 @@ * with spaces. */ auto hHeap = OS.GetProcessHeap (); - TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), fixMnemonic (string), true); + TCHAR[] buffer = StrToTCHARs (parent.getCodePage (), fixMnemonic (string, true), true); int byteCount = buffer.length * TCHAR.sizeof; auto pszText = cast(TCHAR*) OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory (pszText, buffer.ptr, byteCount); diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/TreeItem.d --- a/dwt/widgets/TreeItem.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/TreeItem.d Sat May 17 17:34:28 2008 +0200 @@ -58,11 +58,11 @@ Tree parent; String [] strings; Image [] images; + Font font; + Font [] cellFont; bool cached; int background = -1, foreground = -1; - HFONT font = cast(HFONT)-1; int [] cellBackground, cellForeground; - HFONT[] cellFont; /** * Constructs a new instance of this class given its parent @@ -258,7 +258,7 @@ OS.SendMessage (hwnd, OS.TVM_SETITEM, 0, &tvItem); } background = foreground = -1; - HFONT font = cast(HFONT)-1; + font = null; cellBackground = cellForeground = null; cellFont = null; if ((parent.style & DWT.VIRTUAL) !is 0) cached = false; @@ -340,6 +340,12 @@ releaseHandle (); } +HFONT fontHandle (int index) { + if (cellFont !is null && cellFont [index] !is null) return cellFont [index].handle; + if (font !is null) return font.handle; + return cast(HFONT)-1; +} + /** * Returns the receiver's background color. * @@ -444,14 +450,13 @@ int columnCount = 0; auto hwndHeader = parent.hwndHeader; if (hwndHeader !is null) { - columnCount = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0); + columnCount = parent.columnCount; firstColumn = index is OS.SendMessage (hwndHeader, OS.HDM_ORDERTOINDEX, 0, 0); } RECT rect; if (firstColumn) { - rect.left = cast(int) handle; bool full = columnCount is 0 && getText && getImage && fullText && fullImage; - if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, full ? 0 : 1, cast(int)&rect) is 0) { + if (!OS.TreeView_GetItemRect (hwnd, handle, &rect, !full)) { return RECT.init; } if (getImage && !fullImage) { @@ -474,7 +479,7 @@ headerRect.right = parent.scrollWidth; if (headerRect.right is 0) headerRect = rect; } - if (fullText) rect.right = headerRect.right; + if (fullText && clip) rect.right = headerRect.right; if (fullImage) rect.left = headerRect.left; if (clip && headerRect.right < rect.right) { rect.right = headerRect.right; @@ -487,12 +492,11 @@ if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, cast(int) &headerRect) is 0) { return RECT.init; } - rect.left = cast(int)handle; - if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int) &rect) is 0) { + if (!OS.TreeView_GetItemRect (hwnd, handle, &rect, false)) { return RECT.init; } rect.left = headerRect.left; - if (fullText && getImage) { + if (fullText && getImage && clip) { rect.right = headerRect.right; } else { rect.right = headerRect.left; @@ -507,7 +511,7 @@ rect.right += size.x; } if (getText) { - if (fullText) { + if (fullText && clip) { rect.left = rect.right + Tree.INSET; rect.right = headerRect.right; } else { @@ -520,8 +524,7 @@ HFONT hFont; if (hDC is null) { hNewDC = OS.GetDC (hwnd); - hFont = cellFont !is null ? cellFont [index] : cast(HFONT)-1; - if (hFont is cast(HFONT)-1) hFont = font; + hFont = fontHandle (index); if (hFont is cast(HFONT)-1) hFont = cast(HFONT) OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0); hFont = OS.SelectObject (hNewDC, hFont); } @@ -627,7 +630,7 @@ public Font getFont () { checkWidget (); if (!parent.checkData (this, true)) error (DWT.ERROR_WIDGET_DISPOSED); - return font is cast(HFONT)-1 ? parent.getFont () : Font.win32_new (display, font); + return font !is null ? font : parent.getFont (); } /** @@ -649,8 +652,8 @@ if (!parent.checkData (this, true)) error (DWT.ERROR_WIDGET_DISPOSED); int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count -1) return getFont (); - auto hFont = (cellFont !is null) ? cellFont [index] : font; - return hFont is cast(HFONT)-1 ? getFont () : Font.win32_new (display, hFont); + if (cellFont is null || cellFont [index] is null) return getFont (); + return cellFont [index]; } /** @@ -976,8 +979,6 @@ if (parent.currentItem is this || parent.drawCount !is 0) return; auto hwnd = parent.handle; if (!OS.IsWindowVisible (hwnd)) return; - RECT rect; - rect.left = cast(int)handle; /* * When there are no columns and the tree is not * full selection, redraw only the text. This is @@ -985,17 +986,15 @@ */ bool full = (parent.style & (DWT.FULL_SELECTION | DWT.VIRTUAL)) !is 0; if (!full) { - auto hwndHeader = parent.hwndHeader; - if (hwndHeader !is null) { - full = OS.SendMessage (hwndHeader, OS.HDM_GETITEMCOUNT, 0, 0) !is 0; - } + full = parent.columnCount !is 0; if (!full) { if (parent.hooks (DWT.EraseItem) || parent.hooks (DWT.PaintItem)) { full = true; } } } - if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, full ? 0 : 1, cast(int) &rect) !is 0) { + RECT rect; + if (OS.TreeView_GetItemRect (hwnd, handle, &rect, !full)) { OS.InvalidateRect (hwnd, &rect, true); } } @@ -1178,8 +1177,7 @@ if ((parent.style & DWT.VIRTUAL) !is 0) { if (parent.currentItem is this && OS.IsWindowVisible (hwnd)) { RECT rect; - rect.left = cast(int) handle; - if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int) &rect) !is 0) { + if (OS.TreeView_GetItemRect (hwnd, handle, &rect, false)) { OS.InvalidateRect (hwnd, &rect, true); } } @@ -1238,20 +1236,17 @@ */ RECT oldRect; RECT [] rects = null; - SCROLLINFO oldInfo; - bool oldInfoNull = true; + SCROLLINFO* oldInfo; int count = 0; HANDLE hBottomItem; bool redraw = false, noScroll = true; HANDLE hTopItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); if (noScroll && hTopItem !is null) { - //oldInfo = new SCROLLINFO (); - oldInfoNull = false; + oldInfo = new SCROLLINFO (); oldInfo.cbSize = SCROLLINFO.sizeof; oldInfo.fMask = OS.SIF_ALL; - if (!OS.GetScrollInfo (hwnd, OS.SB_HORZ, &oldInfo)) { - //oldInfo = null; - oldInfoNull = true; + if (!OS.GetScrollInfo (hwnd, OS.SB_HORZ, oldInfo)) { + oldInfo = null; } if (parent.drawCount is 0 && OS.IsWindowVisible (hwnd)) { bool noAnimate = true; @@ -1261,8 +1256,7 @@ int index = 0; while (hItem !is null && (noAnimate || hItem !is handle) && index < count) { RECT rect; - rect.left = cast(int) hItem; - if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 1, cast(int) &rect) !is 0) { + if (OS.TreeView_GetItemRect (hwnd, hItem, &rect, true)) { rects [index++] = rect; } hItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_NEXTVISIBLE, cast(int) &hItem); @@ -1312,10 +1306,8 @@ bool collapsed = false; if (!expanded) { RECT rect; - rect.left = cast(int)hTopItem; - while (hTopItem !is null && OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int) &rect) is 0) { - rect.left = OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hTopItem); - hTopItem = cast(HANDLE) rect.left; + while (hTopItem !is null && !OS.TreeView_GetItemRect (hwnd, hTopItem, &rect, false)) { + hTopItem = cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_PARENT, hTopItem); collapsed = true; } } @@ -1324,13 +1316,13 @@ OS.SendMessage (hwnd, OS.TVM_SELECTITEM, OS.TVGN_FIRSTVISIBLE, hTopItem); scrolled = hTopItem !is cast(HANDLE) OS.SendMessage (hwnd, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0); } - if (!collapsed && !scrolled && !oldInfoNull ) { + if (!collapsed && !scrolled && oldInfo !is null ) { SCROLLINFO newInfo; newInfo.cbSize = SCROLLINFO.sizeof; newInfo.fMask = OS.SIF_ALL; if (OS.GetScrollInfo (hwnd, OS.SB_HORZ, &newInfo)) { if (oldInfo.nPos !is newInfo.nPos) { - int lParam = OS.SB_THUMBPOSITION | ((oldInfo.nPos << 16) & 0xFFFF0000); + int /*long*/ lParam = OS.MAKELPARAM (OS.SB_THUMBPOSITION, oldInfo.nPos); OS.SendMessage (hwnd, OS.WM_HSCROLL, lParam, 0); } } @@ -1345,8 +1337,7 @@ int index = 0; while (hItem !is null && index < count) { RECT rect; - rect.left = cast(int) hItem; - if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 1, cast(int) &rect) !is 0) { + if (OS.TreeView_GetItemRect (hwnd, hItem, &rect, true)) { if (!OS.EqualRect (&rect, & rects [index])) { break; } @@ -1376,8 +1367,7 @@ } if (handle is hBottomItem) { RECT rect; - rect.left = cast(int) hBottomItem; - if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int)&rect) !is 0) { + if (OS.TreeView_GetItemRect (hwnd, hBottomItem, &rect, false)) { OS.InvalidateRect (hwnd, &rect, true); } } @@ -1427,13 +1417,11 @@ if (font !is null && font.isDisposed ()) { DWT.error (DWT.ERROR_INVALID_ARGUMENT); } - HFONT hFont = cast(HFONT)-1; - if (font !is null) { - parent.customDraw = true; - hFont = font.handle; - } - if (this.font is hFont) return; - this.font = hFont; + Font oldFont = this.font; + if (oldFont is font) return; + this.font = font; + if (oldFont !is null && oldFont.opEquals (font)) return; + if (font !is null) parent.customDraw = true; if ((parent.style & DWT.VIRTUAL) !is 0) cached = true; /* * Bug in Windows. When the font is changed for an item, @@ -1479,19 +1467,15 @@ } int count = Math.max (1, parent.getColumnCount ()); if (0 > index || index > count - 1) return; - HFONT hFont = cast(HFONT)-1; - if (font !is null) { - parent.customDraw = true; - hFont = font.handle; + if (cellFont is null) { + if (font is null) return; + cellFont = new Font [count]; } - if (cellFont is null) { - cellFont = new HFONT [count]; - for (int i = 0; i < count; i++) { - cellFont [i] = cast(HFONT) -1; - } - } - if (cellFont [index] is hFont) return; - cellFont [index] = hFont; + Font oldFont = cellFont [index]; + if (oldFont is font) return; + cellFont [index] = font; + if (oldFont !is null && oldFont.opEquals (font)) return; + if (font !is null) parent.customDraw = true; if ((parent.style & DWT.VIRTUAL) !is 0) cached = true; /* * Bug in Windows. When the font is changed for an item, @@ -1633,8 +1617,7 @@ if ((parent.style & DWT.VIRTUAL) !is 0) { if (parent.currentItem is this && OS.IsWindowVisible (hwnd)) { RECT rect; - rect.left = cast(int)handle; - if (OS.SendMessage (hwnd, OS.TVM_GETITEMRECT, 0, cast(int)&rect) !is 0) { + if (OS.TreeView_GetItemRect (hwnd, handle, &rect, false)) { OS.InvalidateRect (hwnd, &rect, true); } } diff -r ab60f3309436 -r 36f5cb12e1a2 dwt/widgets/Widget.d --- a/dwt/widgets/Widget.d Mon May 05 00:12:38 2008 +0200 +++ b/dwt/widgets/Widget.d Sat May 17 17:34:28 2008 +0200 @@ -101,6 +101,15 @@ static const int FOREIGN_HANDLE = 1<<14; static const int DRAG_DETECT = 1<<15; + /* Move and resize state flags */ + static final int MOVE_OCCURRED = 1<<16; + static final int MOVE_DEFERRED = 1<<17; + static final int RESIZE_OCCURRED = 1<<18; + static final int RESIZE_DEFERRED = 1<<19; + + /* Ignore WM_CHANGEUISTATE */ + static final int IGNORE_WM_CHANGEUISTATE = 1<<20; + /* Default size for widgets */ static const int DEFAULT_WIDTH = 64; static const int DEFAULT_HEIGHT = 64; @@ -197,6 +206,7 @@ * * @see Listener * @see DWT + * @see #getListeners(int) * @see #removeListener(int, Listener) * @see #notifyListeners */ @@ -357,7 +367,27 @@ void checkWidget () { Display display = this.display; if (display is null) error (DWT.ERROR_WIDGET_DISPOSED); - if (display.thread !is Thread.getThis ()) error (DWT.ERROR_THREAD_INVALID_ACCESS); + if (display.thread !is Thread.getThis ()) { + /* + * Bug in IBM JVM 1.6. For some reason, under + * conditions that are yet to be full understood, + * Thread.currentThread() is either returning null + * or a different instance from the one that was + * saved when the Display was created. This is + * possibly a JIT problem because modifying this + * method to print logging information when the + * error happens seems to fix the problem. The + * fix is to use operating system calls to verify + * that the current thread is not the Display thread. + * + * NOTE: Despite the fact that Thread.currentThread() + * is used in other places, the failure has only been + * observed here. + */ + if (display.threadId !is OS.GetCurrentThreadId ()) { + error (DWT.ERROR_THREAD_INVALID_ACCESS); + } + } if ((state & DISPOSED) !is 0) error (DWT.ERROR_WIDGET_DISPOSED); } @@ -475,12 +505,17 @@ } char [] fixMnemonic (String string) { - char [] buffer = string.dup; + return fixMnemonic (string, false); +} + +char [] fixMnemonic (String string, bool spaces) { + char [] buffer = string ~ '\0'; int i = 0, j = 0; while (i < buffer.length) { if (buffer [i] is '&') { if (i + 1 < buffer.length && buffer [i + 1] is '&') { - buffer [j++] = ' '; + if (spaces) buffer [j] = ' '; + j++; i++; } i++; @@ -577,6 +612,33 @@ return display; } +/** + * Returns an array of listeners who will be notified when an event + * of the given type occurs. The event type is one of the event constants + * defined in class DWT. + * + * @param eventType the type of event to listen for + * @return an array of listeners that will be notified when the event occurs + * + * @exception DWTException
            + *
          • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
          • + *
          • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
          • + *
          + * + * @see Listener + * @see DWT + * @see #addListener(int, Listener) + * @see #removeListener(int, Listener) + * @see #notifyListeners + * + * @since 3.4 + */ +public Listener[] getListeners (int eventType) { + checkWidget(); + if (eventTable is null) return new Listener[0]; + return eventTable.getListeners(eventType); +} + Menu getMenu () { return null; } @@ -732,6 +794,7 @@ * * @see DWT * @see #addListener + * @see #getListeners(int) * @see #removeListener(int, Listener) */ public void notifyListeners (int eventType, Event event) { @@ -880,6 +943,7 @@ * @see Listener * @see DWT * @see #addListener + * @see #getListeners(int) * @see #notifyListeners */ public void removeListener (int eventType, Listener listener) { @@ -999,13 +1063,13 @@ } } -bool sendKeyEvent (int type, int msg, int wParam, int lParam) { +bool sendKeyEvent (int type, int msg, int /*long*/ wParam, int /*long*/ lParam) { Event event = new Event (); if (!setKeyState (event, type, wParam, lParam)) return true; return sendKeyEvent (type, msg, wParam, lParam, event); } -bool sendKeyEvent (int type, int msg, int wParam, int lParam, Event event) { +bool sendKeyEvent (int type, int msg, int /*long*/ wParam, int /*long*/ lParam, Event event) { sendEvent (type, event); if (isDisposed ()) return false; return event.doit; @@ -1021,8 +1085,8 @@ event.button = button; event.detail = detail; event.count = count; - event.x = cast(short) (lParam & 0xFFFF); - event.y = cast(short) (lParam >> 16); + event.x = OS.GET_X_LPARAM (lParam); + event.y = OS.GET_Y_LPARAM (lParam); setInputState (event, type); mapEvent (hwnd, event); if (send) { @@ -1149,8 +1213,10 @@ if (OS.GetKeyState (OS.VK_LBUTTON) < 0) event.stateMask |= DWT.BUTTON1; if (OS.GetKeyState (OS.VK_MBUTTON) < 0) event.stateMask |= DWT.BUTTON2; if (OS.GetKeyState (OS.VK_RBUTTON) < 0) event.stateMask |= DWT.BUTTON3; - if (OS.GetKeyState (OS.VK_XBUTTON1) < 0) event.stateMask |= DWT.BUTTON4; - if (OS.GetKeyState (OS.VK_XBUTTON2) < 0) event.stateMask |= DWT.BUTTON5; + if (display.xMouse) { + if (OS.GetKeyState (OS.VK_XBUTTON1) < 0) event.stateMask |= DWT.BUTTON4; + if (OS.GetKeyState (OS.VK_XBUTTON2) < 0) event.stateMask |= DWT.BUTTON5; + } switch (type) { case DWT.MouseDown: case DWT.MouseDoubleClick: @@ -1183,7 +1249,7 @@ return true; } -bool setKeyState (Event event, int type, int wParam, int lParam) { +bool setKeyState (Event event, int type, int /*long*/ wParam, int /*long*/ lParam) { /* * Feature in Windows. When the user presses Ctrl+Backspace @@ -1357,16 +1423,16 @@ int x = 0, y = 0; if (lParam !is -1) { POINT pt; - x = pt.x = cast(short) (lParam & 0xFFFF); - y = pt.y = cast(short) (lParam >> 16); - OS.ScreenToClient (hwnd, &pt); + OS.POINTSTOPOINT (pt, lParam); + x = pt.x; + y = pt.y; RECT rect; OS.GetClientRect (hwnd, &rect); if (!OS.PtInRect (&rect, pt)) return null; } else { int pos = OS.GetMessagePos (); - x = cast(short) (pos & 0xFFFF); - y = cast(short) (pos >> 16); + x = OS.GET_X_LPARAM (pos); + y = OS.GET_Y_LPARAM (pos); } /* Show the menu */ @@ -1434,7 +1500,22 @@ default: } } else { - mapKey = OS.MapVirtualKey (wParam, 2); + /* + * Feature in Windows. For numbers in Marathi and Bengali, + * MapVirtualKey() returns the localized number instead of + * the ASCII equivalent. For example, MapVirtualKey() + * maps VK_1 on the Marathi keyboard to \u2407, which is + * a valid Unicode Marathi '1' character, but not ASCII. + * The fix is to test for VK_0 to VK_9 and map these + * explicitly. + * + * NOTE: VK_0 to VK_9 are the same as ASCII. + */ + if ('0' <= wParam && wParam <= '9') { + mapKey = wParam; + } else { + mapKey = OS.MapVirtualKey (wParam, 2); + } } /* @@ -1718,6 +1799,7 @@ } LRESULT wmKillFocus (HWND hwnd, int wParam, int lParam) { + display.scrollRemainder = 0; int code = callWindowProc (hwnd, OS.WM_KILLFOCUS, wParam, lParam); sendFocusEvent (DWT.FocusOut); // widget could be disposed at this point @@ -1766,8 +1848,8 @@ LRESULT wmLButtonDown (HWND hwnd, int wParam, int lParam) { Display display = this.display; LRESULT result = null; - int x = cast(short) (lParam & 0xFFFF); - int y = cast(short) (lParam >> 16); + int x = OS.GET_X_LPARAM (lParam); + int y = OS.GET_Y_LPARAM (lParam); bool [] consume = null, detect = null; bool dragging = false, mouseDown = true; int count = display.getClickCount (DWT.MouseDown, 1, hwnd, lParam); @@ -1871,7 +1953,7 @@ */ int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON; if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2; - if (((wParam & 0xFFFF) & mask) is 0) { + if ((wParam & mask) is 0) { if (OS.GetCapture () is hwnd) OS.ReleaseCapture (); } return result; @@ -1937,7 +2019,7 @@ */ int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON; if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2; - if (((wParam & 0xFFFF) & mask) is 0) { + if ((wParam & mask) is 0) { if (OS.GetCapture () is hwnd) OS.ReleaseCapture (); } return result; @@ -1954,10 +2036,9 @@ if (!hooks (DWT.MouseExit) && !filters (DWT.MouseExit)) return null; int pos = OS.GetMessagePos (); POINT pt; - pt.x = cast(short) (pos & 0xFFFF); - pt.y = cast(short) (pos >> 16); + OS.POINTSTOPOINT (pt, pos); OS.ScreenToClient (hwnd, &pt); - lParam = (pt.x & 0xFFFF) | ((pt.y << 16) & 0xFFFF0000); + lParam = OS.MAKELPARAM (pt.x, pt.y); if (!sendMouseEvent (DWT.MouseExit, 0, hwnd, OS.WM_MOUSELEAVE, wParam, lParam)) { return LRESULT.ZERO; } @@ -2017,30 +2098,37 @@ } LRESULT wmMouseWheel (HWND hwnd, int wParam, int lParam) { - if (!hooks (DWT.MouseWheel) && !filters (DWT.MouseWheel)) return null; - int delta = wParam >> 16; - int value; - int count, detail; - OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &value, 0); - if (value is OS.WHEEL_PAGESCROLL) { + int delta = OS.GET_WHEEL_DELTA_WPARAM (wParam); + int linesToScroll; + int detail; + OS.SystemParametersInfo (OS.SPI_GETWHEELSCROLLLINES, 0, &linesToScroll, 0); + if (linesToScroll is OS.WHEEL_PAGESCROLL) { detail = DWT.SCROLL_PAGE; - count = delta / OS.WHEEL_DELTA; } else { detail = DWT.SCROLL_LINE; - count = value * delta / OS.WHEEL_DELTA; + delta *= linesToScroll; } + /* Check if the delta and the remainder have the same direction (sign) */ + if ((delta ^ display.scrollRemainder) >= 0) delta += display.scrollRemainder; + display.scrollRemainder = delta % OS.WHEEL_DELTA; + + if (!hooks (DWT.MouseWheel) && !filters (DWT.MouseWheel)) return null; + int count = delta / OS.WHEEL_DELTA; POINT pt; - pt.x = cast(short) (lParam & 0xFFFF); - pt.y = cast(short) (lParam >> 16); + OS.POINTSTOPOINT (pt, lParam); OS.ScreenToClient (hwnd, &pt); - lParam = (pt.x & 0xFFFF) | ((pt.y << 16) & 0xFFFF0000); + lParam = OS.MAKELPARAM (pt.x, pt.y); if (!sendMouseEvent (DWT.MouseWheel, 0, count, detail, true, hwnd, OS.WM_MOUSEWHEEL, wParam, lParam)) { return LRESULT.ZERO; } return null; } -LRESULT wmPaint (HWND hwnd, int wParam, int lParam) { +LRESULT wmNCPaint (HWND hwnd, int /*long*/ wParam, int /*long*/ lParam) { + return null; +} + +LRESULT wmPaint (HWND hwnd, int /*long*/ wParam, int /*long*/ lParam) { /* Exit early - don't draw the background */ if (!hooks (DWT.Paint) && !filters (DWT.Paint)) { @@ -2048,7 +2136,7 @@ } /* Issue a paint event */ - int result = 0; + int /*long*/ result = 0; static if (OS.IsWinCE) { RECT rect; OS.GetUpdateRect (hwnd, &rect, false); @@ -2132,7 +2220,7 @@ if (OS.COMCTL32_MAJOR >= 6 && OS.IsAppThemed ()) { int bits = OS.GetWindowLong (hwnd, OS.GWL_EXSTYLE); if ((bits & OS.WS_EX_CLIENTEDGE) !is 0) { - int code = callWindowProc (hwnd, OS.WM_PRINT, wParam, lParam); + int /*long*/ code = callWindowProc (hwnd, OS.WM_PRINT, wParam, lParam); RECT rect; OS.GetWindowRect (hwnd, &rect); rect.right -= rect.left; @@ -2210,14 +2298,14 @@ */ int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON; if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2; - if (((wParam & 0xFFFF) & mask) is 0) { + if ((wParam & mask) is 0) { if (OS.GetCapture () is hwnd) OS.ReleaseCapture (); } return result; } LRESULT wmSetFocus (HWND hwnd, int wParam, int lParam) { - int code = callWindowProc (hwnd, OS.WM_SETFOCUS, wParam, lParam); + int /*long*/ code = callWindowProc (hwnd, OS.WM_SETFOCUS, wParam, lParam); sendFocusEvent (DWT.FocusIn); // widget could be disposed at this point @@ -2246,7 +2334,7 @@ /* Call the window proc to determine whether it is a system key or mnemonic */ bool oldKeyHit = display.mnemonicKeyHit; display.mnemonicKeyHit = true; - int result = callWindowProc (hwnd, OS.WM_SYSCHAR, wParam, lParam); + int /*long*/ result = callWindowProc (hwnd, OS.WM_SYSCHAR, wParam, lParam); bool consumed = false; if (!display.mnemonicKeyHit) { consumed = !sendKeyEvent (DWT.KeyDown, OS.WM_SYSCHAR, wParam, lParam); @@ -2405,7 +2493,7 @@ LRESULT result = null; Display display = this.display; display.captureChanged = false; - int button = (wParam >> 16 is OS.XBUTTON1) ? 4 : 5; + int button = OS.HIWORD (wParam) is OS.XBUTTON1 ? 4 : 5; sendMouseEvent (DWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam); if (sendMouseEvent (DWT.MouseDoubleClick, button, hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam)) { result = new LRESULT (callWindowProc (hwnd, OS.WM_XBUTTONDBLCLK, wParam, lParam)); @@ -2423,7 +2511,7 @@ Display display = this.display; display.captureChanged = false; display.xMouse = true; - int button = (wParam >> 16 is OS.XBUTTON1) ? 4 : 5; + int button = OS.HIWORD (wParam) is OS.XBUTTON1 ? 4 : 5; if (sendMouseEvent (DWT.MouseDown, button, hwnd, OS.WM_XBUTTONDOWN, wParam, lParam)) { result = new LRESULT (callWindowProc (hwnd, OS.WM_XBUTTONDOWN, wParam, lParam)); } else { @@ -2438,7 +2526,7 @@ LRESULT wmXButtonUp (HWND hwnd, int wParam, int lParam) { Display display = this.display; LRESULT result = null; - int button = (wParam >> 16 is OS.XBUTTON1) ? 4 : 5; + int button = OS.HIWORD (wParam) is OS.XBUTTON1 ? 4 : 5; if (sendMouseEvent (DWT.MouseUp, button, hwnd, OS.WM_XBUTTONUP, wParam, lParam)) { result = new LRESULT (callWindowProc (hwnd, OS.WM_XBUTTONUP, wParam, lParam)); } else { @@ -2452,7 +2540,7 @@ */ int mask = OS.MK_LBUTTON | OS.MK_MBUTTON | OS.MK_RBUTTON; if (display.xMouse) mask |= OS.MK_XBUTTON1 | OS.MK_XBUTTON2; - if (((wParam & 0xFFFF) & mask) is 0) { + if ((wParam & mask) is 0) { if (OS.GetCapture () is hwnd) OS.ReleaseCapture (); } return result;