?? menuitem.java
字號:
* 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. */ if (!OS.IsWinCE && (OS.WIN32_MAJOR << 16 | OS.WIN32_MINOR) >= (4 << 16 | 10)) { info.fMask = OS.MIIM_BITMAP; OS.GetMenuItemInfo (hMenu, index, true, info); hasBitmap = info.hbmpItem != 0; if (hasBitmap) { info.hbmpItem = 0; success = OS.SetMenuItemInfo (hMenu, id, false, info); } } int cch = 128; int hHeap = OS.GetProcessHeap (); int byteCount = cch * TCHAR.sizeof; int pszText = 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 = OS.GetMenuItemInfo (hMenu, index, true, info); if (menu != null) { menu.cascade = this; info.fMask |= OS.MIIM_SUBMENU; info.hSubMenu = menu.handle; } OS.RemoveMenu (hMenu, index, OS.MF_BYPOSITION); if (OS.IsWinCE) { /* * On WinCE, InsertMenuItem() is not available. The fix is to * use SetMenuItemInfo() but this call does not set the menu item * state and submenu. The fix is to use InsertMenu() to insert * the item, SetMenuItemInfo() to set the string and EnableMenuItem() * and CheckMenuItem() to set the state. */ int uIDNewItem = id; int uFlags = OS.MF_BYPOSITION; if (menu != null) { uFlags |= OS.MF_POPUP; uIDNewItem = menu.handle; } TCHAR lpNewItem = new TCHAR (0, " ", true); success = OS.InsertMenu (hMenu, index, uFlags, uIDNewItem, lpNewItem); if (success) { info.fMask = OS.MIIM_DATA | OS.MIIM_TYPE; success = OS.SetMenuItemInfo (hMenu, index, true, info); if ((info.fState & (OS.MFS_DISABLED | OS.MFS_GRAYED)) != 0) { OS.EnableMenuItem (hMenu, index, OS.MF_BYPOSITION | OS.MF_GRAYED); } if ((info.fState & OS.MFS_CHECKED) != 0) { OS.CheckMenuItem (hMenu, index, OS.MF_BYPOSITION | OS.MF_CHECKED); } } } else { success = 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_MAJOR << 16 | OS.WIN32_MINOR) >= (4 << 16 | 10)) { if (hasBitmap) { info.fMask = OS.MIIM_BITMAP; info.hbmpItem = OS.HBMMENU_CALLBACK; success = OS.SetMenuItemInfo (hMenu, id, false, info); } } } if (pszText != 0) OS.HeapFree (hHeap, 0, pszText); if (!success) error (SWT.ERROR_CANNOT_SET_MENU); } parent.destroyAccelerators ();}boolean setRadioSelection (boolean value) { if ((style & SWT.RADIO) == 0) return false; if (getSelection () != value) { setSelection (value); postEvent (SWT.Selection); } return true;}/** * Sets the selection state of the receiver. * <p> * When the receiver is of type <code>CHECK</code> or <code>RADIO</code>, * it is selected when it is checked. * * @param selected the new selection state * * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> */public void setSelection (boolean selected) { checkWidget (); if ((style & (SWT.CHECK | SWT.RADIO)) == 0) return; if ((OS.IsPPC || OS.IsSP) && parent.hwndCB != 0) return; int hMenu = parent.handle; if (OS.IsWinCE) { int index = parent.indexOf (this); if (index == -1) return; int uCheck = OS.MF_BYPOSITION | (selected ? OS.MF_CHECKED : OS.MF_UNCHECKED); OS.CheckMenuItem (hMenu, index, uCheck); } else { MENUITEMINFO info = new MENUITEMINFO (); info.cbSize = MENUITEMINFO.sizeof; info.fMask = OS.MIIM_STATE; boolean success = OS.GetMenuItemInfo (hMenu, id, false, info); if (!success) error (SWT.ERROR_CANNOT_SET_SELECTION); info.fState &= ~OS.MFS_CHECKED; if (selected) info.fState |= OS.MFS_CHECKED; success = OS.SetMenuItemInfo (hMenu, id, false, info); if (!success) error (SWT.ERROR_CANNOT_SET_SELECTION); } parent.redraw ();}/** * Sets the receiver's text. The string may include * the mnemonic character and accelerator text. * <p> * Mnemonics are indicated by an '&' that causes the next * character to be the mnemonic. When the user presses a * key sequence that matches the mnemonic, a selection * event occurs. On most platforms, the mnemonic appears * underlined but may be emphasised in a platform specific * manner. The mnemonic indicator character '&' can be * escaped by doubling it in the string, causing a single *'&' to be displayed. * </p> * <p> * Accelerator text is indicated by the '\t' character. * On platforms that support accelerator text, the text * that follows the '\t' character is displayed to the user, * typically indicating the key stroke that will cause * the item to become selected. On most platforms, the * accelerator text appears right aligned in the menu. * Setting the accelerator text does not install the * accelerator key sequence. The accelerator key sequence * is installed using #setAccelerator. * </p> * * @param string the new text * * @exception IllegalArgumentException <ul> * <li>ERROR_NULL_ARGUMENT - if the text is null</li> * </ul> * @exception SWTException <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> * </ul> * * @see #setAccelerator */public void setText (String string) { checkWidget (); if (string == null) error (SWT.ERROR_NULL_ARGUMENT); if ((style & SWT.SEPARATOR) != 0) return; if (text.equals (string)) return; super.setText (string); int hHeap = OS.GetProcessHeap (); int pszText = 0; boolean success = false; if ((OS.IsPPC || OS.IsSP) && parent.hwndCB != 0) { /* * Bug in WinCE PPC. Tool items on the menubar don't resize * correctly when the character '&' is used (even when it * is a sequence '&&'). The fix is to remove all '&' from * the string. */ if (string.indexOf ('&') != -1) { int length = string.length (); char[] text = new char [length]; string.getChars( 0, length, text, 0); int i = 0, j = 0; for (i=0; i<length; i++) { if (text[i] != '&') text [j++] = text [i]; } if (j < i) string = new String (text, 0, j); } /* Use the character encoding for the default locale */ TCHAR buffer = new TCHAR (0, string, true); int byteCount = buffer.length () * TCHAR.sizeof; pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory (pszText, buffer, byteCount); int hwndCB = parent.hwndCB; TBBUTTONINFO info2 = new TBBUTTONINFO (); info2.cbSize = TBBUTTONINFO.sizeof; info2.dwMask = OS.TBIF_TEXT; info2.pszText = pszText; success = OS.SendMessage (hwndCB, OS.TB_SETBUTTONINFO, id, info2) != 0; } else { MENUITEMINFO info = new MENUITEMINFO (); info.cbSize = MENUITEMINFO.sizeof; int 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. */ boolean hasBitmap = false; if (!OS.IsWinCE && (OS.WIN32_MAJOR << 16 | OS.WIN32_MINOR) >= (4 << 16 | 10)) { info.fMask = OS.MIIM_BITMAP; OS.GetMenuItemInfo (hMenu, id, false, info); hasBitmap = info.hbmpItem != 0; } /* Use the character encoding for the default locale */ TCHAR buffer = new TCHAR (0, string, true); int byteCount = buffer.length () * TCHAR.sizeof; pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory (pszText, buffer, byteCount); info.fMask = OS.MIIM_TYPE; info.fType = widgetStyle (); info.dwTypeData = pszText; success = 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. */ if (!OS.IsWinCE && (OS.WIN32_MAJOR << 16 | OS.WIN32_MINOR) >= (4 << 16 | 10)) { if (hasBitmap) { info.fMask = OS.MIIM_BITMAP; info.hbmpItem = OS.HBMMENU_CALLBACK; success = OS.SetMenuItemInfo (hMenu, id, false, info); } } } if (pszText != 0) OS.HeapFree (hHeap, 0, pszText); if (!success) error (SWT.ERROR_CANNOT_SET_TEXT); parent.redraw ();}int widgetStyle () { int bits = 0; Decorations shell = parent.parent; if ((shell.style & SWT.MIRRORED) != 0) { if ((parent.style & SWT.LEFT_TO_RIGHT) != 0) { bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER; } } else { if ((parent.style & SWT.RIGHT_TO_LEFT) != 0) { bits |= OS.MFT_RIGHTJUSTIFY | OS.MFT_RIGHTORDER; } } if ((style & SWT.SEPARATOR) != 0) return bits | OS.MFT_SEPARATOR; if ((style & SWT.RADIO) != 0) return bits | OS.MFT_RADIOCHECK; return bits | OS.MFT_STRING;}LRESULT wmCommandChild (int wParam, int lParam) { if ((style & SWT.CHECK) != 0) { setSelection (!getSelection ()); } else { if ((style & SWT.RADIO) != 0) { if ((parent.getStyle () & SWT.NO_RADIO_GROUP) != 0) { setSelection (!getSelection ()); } else { selectRadio (); } } } Event event = new Event (); setInputState (event, SWT.Selection); postEvent (SWT.Selection, event); return null;}LRESULT wmDrawChild (int wParam, int lParam) { DRAWITEMSTRUCT struct = new DRAWITEMSTRUCT (); OS.MoveMemory (struct, lParam, DRAWITEMSTRUCT.sizeof); if (image != null) { GCData data = new GCData(); data.device = display; GC gc = GC.win32_new (struct.hDC, data); /* * Bug in Windows. When a bitmap is included in the * menu bar, the HDC seems to already include the left * coordinate. The fix is to ignore this value when * the item is in a menu bar. */ int x = (parent.style & SWT.BAR) != 0 ? (OS.IsWin95 ? 4 : 2) : struct.left; gc.drawImage (image, x, struct.top + 2); gc.dispose (); } return null;}LRESULT wmMeasureChild (int wParam, int lParam) { MEASUREITEMSTRUCT struct = new MEASUREITEMSTRUCT (); OS.MoveMemory (struct, lParam, MEASUREITEMSTRUCT.sizeof); int width = 0, height = 0; if (image != null) { Rectangle rect = image.getBounds (); width = rect.width; height = rect.height; } else { /* * Bug in Windows. If a menu contains items that have * images and can be checked, Windows does not include * the width of the image and the width of the check when * computing the width of the menu. When the longest item * does not have an image, the label and the accelerator * text can overlap. The fix is to use SetMenuItemInfo() * to indicate that all items have a bitmap and then include * the width of the widest bitmap in WM_MEASURECHILD. */ MENUINFO lpcmi = new MENUINFO (); lpcmi.cbSize = MENUINFO.sizeof; lpcmi.fMask = OS.MIM_STYLE; int hMenu = parent.handle; OS.GetMenuInfo (hMenu, lpcmi); if ((lpcmi.dwStyle & OS.MNS_CHECKORBMP) == 0) { MenuItem [] items = parent.getItems (); for (int i=0; i<items.length; i++) { MenuItem item = items [i]; if (item.image != null) { Rectangle rect = item.image.getBounds (); width = Math.max (width, rect.width); } } } } if (width != 0 || height != 0) { /* * Feature in Windows. On Windows 98, it is necessary * to add 4 pixels to the width of the image or the image * and text are too close. On other Windows platforms, * this causes the text of the longest item to touch the * accelerator text. The fix is to add only 2 pixels in * this case. */ struct.itemWidth = width + (OS.IsWin95 ? 4 : 2); struct.itemHeight = height + 4; OS.MoveMemory (lParam, struct, MEASUREITEMSTRUCT.sizeof); } return null;}}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -