diff options
author | Raymond Lam | 2011-10-23 15:19:06 +0000 |
---|---|---|
committer | Felipe Heidrich | 2011-11-11 15:35:27 +0000 |
commit | afa64269dcd7778f6eb01e1cb2d17a3455e7a43e (patch) | |
tree | af9dc8ff83f294feea36e594ec329d3014149f6d | |
parent | 302cd8903e1bf188479e00162eeb753ae5ca540f (diff) | |
download | eclipse.platform.swt-afa64269dcd7778f6eb01e1cb2d17a3455e7a43e.tar.gz eclipse.platform.swt-afa64269dcd7778f6eb01e1cb2d17a3455e7a43e.tar.xz eclipse.platform.swt-afa64269dcd7778f6eb01e1cb2d17a3455e7a43e.zip |
Glassify the Button widget.
-rw-r--r-- | bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java | 188 |
1 files changed, 187 insertions, 1 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java index 0f87d79aa9..63427a7b47 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java @@ -641,7 +641,9 @@ boolean getBufferredPaint() { if ((shell.style & SWT.TRIM_FILL) != 0) { if ((style & SWT.PUSH) != 0) return true; if ((style & SWT.TOGGLE) != 0) return true; - //what about radio, check, and arrow ? should be transparent with custom draw ? + if ((style & SWT.RADIO) != 0) return true; + if ((style & SWT.CHECK) != 0) return true; + //what about arrow ? should be transparent with custom draw ? } return false; } @@ -1426,4 +1428,188 @@ LRESULT wmDrawChild (int /*long*/ wParam, int /*long*/ lParam) { return null; } +LRESULT wmBufferedPaint (int /*long*/ hWnd, int /*long*/ wParam, int /*long*/ lParam) { + int /*long*/ paintDC = 0; + PAINTSTRUCT ps = new PAINTSTRUCT (); + paintDC = OS.BeginPaint (hWnd, ps); + + RECT rcClient = new RECT(); + OS.GetClientRect(hWnd, rcClient); + + // setup the theme parameters + int /*long*/ hTheme = OS.OpenThemeData(0, "Button;".toCharArray()); + int iPartId = ((style & SWT.PUSH) != 0 || (style & SWT.TOGGLE) != 0) ? OS.BP_PUSHBUTTON : ((style & SWT.RADIO) != 0) ? OS.BP_RADIOBUTTON : OS.BP_CHECKBOX; + int iState = ((style & SWT.PUSH) != 0 || (style & SWT.TOGGLE) != 0) ? determineStateOfPushButton() : determineStateOfRadioOrCheck(); + + // initialize the buffered painting device context + BP_PAINTPARAMS params = new BP_PAINTPARAMS(); + params.cbSize = BP_PAINTPARAMS.sizeof; + params.dwFlags = OS.BPPF_ERASE; + int /*long*/ [] hdcBuffered = new int /*long*/ [1]; + int hBufferedPaint = OS.BeginBufferedPaint(paintDC, rcClient, OS.BPBF_TOPDOWNDIB, params, hdcBuffered); + OS.PatBlt(hdcBuffered[0], 0, 0, rcClient.right, rcClient.bottom, OS.BLACKNESS); + OS.BufferedPaintSetAlpha(hdcBuffered[0], rcClient, (byte)0x00); + + // the DrawThemeBackground will draw the radio button or checkbox in the middle of the button's client + // area, and hence we need shift the painting rectangle off to the left if this is not a pushbutton + int bitmapWidth = ((style & SWT.PUSH) != 0 || (style & SWT.TOGGLE) != 0) ? 0 : this.getThemeBitmapWidth(hTheme, iPartId, iState); + int bitmapOffset = ((style & SWT.PUSH) != 0 || (style & SWT.TOGGLE) != 0) ? 0 : (rcClient.right - rcClient.left) / 2 - bitmapWidth / 2; + RECT rcBackground = new RECT(); + rcBackground.top = rcClient.top; + rcBackground.bottom = rcClient.bottom; + rcBackground.left = rcClient.left - bitmapOffset; + rcBackground.right = rcClient.right - bitmapOffset; + + // get the coords of the content rectangle and draw the background bitmap (the content rectangle is later fed into + // DrawThemeTextEx and is also used for the focus rectangle) + RECT rcContent = new RECT(); + OS.GetThemeBackgroundContentRect(hTheme, hdcBuffered[0], iPartId, iState, rcClient, rcContent); + OS.DrawThemeBackground(hTheme, hdcBuffered[0], iPartId, iState, rcBackground, null); + + // setup the DTTOPTS structure for calling into DrawThemeTextEx - note how we call getThemeGlowSize() + // to apply a glow around the text we are drawing to enhance readability of the text against a glass background + DTTOPTS dttOpts =new DTTOPTS(); + dttOpts.dwSize = DTTOPTS.sizeof; + dttOpts.dwFlags = OS.DTT_COMPOSITED | OS.DTT_GLOWSIZE; + dttOpts.iGlowSize = BufferedPainter.getThemeGlowSize(); + + // set font before drawing the text + int /*long*/ hFont = OS.SendMessage(this.handle, OS.WM_GETFONT, 0, 0); + if (hFont != 0) { + hFont = OS.SelectObject(hdcBuffered[0], hFont); + } + + // draw the button text in an aero/glass friendly manner + rcContent.left += bitmapWidth; // adjust the drawing rectangle to accomodate for the bitmap in case of radio or checkbox + int dwFlags = OS.DT_SINGLELINE | OS.DT_CENTER | OS.DT_VCENTER; + TCHAR buffer = new TCHAR (getCodePage (), text, true); + OS.DrawThemeTextEx(hTheme, hdcBuffered[0], iPartId, iState, buffer.chars, buffer.length()-1, dwFlags, rcContent, dttOpts); + + // draw the focus rectangle if needed + if (OS.GetFocus()==this.handle) { + OS.DrawFocusRect(hdcBuffered[0], rcContent); + } + + // restore font + if (hFont != 0) { + OS.SelectObject(hdcBuffered[0], hFont); + } + + OS.EndBufferedPaint(hBufferedPaint, true); + OS.CloseThemeData(hTheme); + OS.EndPaint (handle, ps); + return LRESULT.ZERO; +} + +/* + * Reference vsstyle.h in the Windows SDK. + * + * Return the button style for the PushButton or the ToggleButton. Button styles come in various flavors: disabled, pressed, hot, default + * and normal. + * + */ +int determineStateOfPushButton() +{ + POINT ptCursor = new POINT(); + RECT rectWindow = new RECT(); + OS.GetWindowRect(this.handle, rectWindow); + OS.GetCursorPos(ptCursor); + boolean hovering = OS.PtInRect(rectWindow, ptCursor); + boolean captured = (OS.GetCapture() == this.handle); + + // see if the button is in a disabled state + if (this.getEnabled() == false) { + return OS.PBS_DISABLED; + } + + // is the button pressed? + if (hovering && captured) { + return OS.PBS_PRESSED; + } + + // does the button have focus + if (hovering || captured) { + return OS.PBS_HOT; + } + + // is the button toggled on? + int dwCheckState = OS.SendMessage(this.handle, OS.BM_GETCHECK, 0, 0); + if (dwCheckState == OS.BST_CHECKED) { + return OS.PBS_PRESSED; + } + + // is this the default button? + if (this.getDefault()) { + return OS.PBS_DEFAULTED; + } + + // normal button + return OS.PBS_NORMAL; +} + + +/* + * Reference vsstyle.h in the Windows SDK. + * + * Button states will determine which bitmap the theme will draw in the background. The visual state comes in 4 states: normal, hot, pressed or + * disabled. These 4 visual states are then combined with the checked/unchecked state of the button (in the case of the check box, there's + * a 3rd checked state of indeterminate), yielding the final button state that is returned. + * + */ +int determineStateOfRadioOrCheck() +{ + POINT ptCursor = new POINT(); + RECT rectWindow = new RECT(); + OS.GetWindowRect(this.handle, rectWindow); + OS.GetCursorPos(ptCursor); + boolean hovering = OS.PtInRect(rectWindow, ptCursor); + boolean captured = (OS.GetCapture() == this.handle); + int dwCheckState = OS.SendMessage(this.handle, OS.BM_GETCHECK, 0, 0); + + // see if the button is in a disabled state + if (this.getEnabled() == false) { + if ((style & SWT.RADIO) != 0) { // radio button + return (dwCheckState == OS.BST_CHECKED) ? OS.RBS_CHECKEDDISABLED : OS.RBS_UNCHECKEDDISABLED; + } else { // checkbox button + return (dwCheckState == OS.BST_CHECKED) ? OS.CBS_CHECKEDDISABLED : (dwCheckState == OS.BST_UNCHECKED) ? OS.CBS_UNCHECKEDDISABLED : OS.CBS_MIXEDDISABLED; + } + } + + // is the button pressed? + if (hovering && captured) { + if ((style & SWT.RADIO) != 0) { // radio button + return (dwCheckState == OS.BST_CHECKED) ? OS.RBS_CHECKEDPRESSED : OS.RBS_UNCHECKEDPRESSED; + } else { // checkbox button + return (dwCheckState == OS.BST_CHECKED) ? OS.CBS_CHECKEDPRESSED : (dwCheckState == OS.BST_UNCHECKED) ? OS.CBS_UNCHECKEDPRESSED : OS.CBS_MIXEDPRESSED; + } + } + + // does the button have focus? + if (hovering || captured) { + if ((style & SWT.RADIO) != 0) { // radio button + return (dwCheckState == OS.BST_CHECKED) ? OS.RBS_CHECKEDHOT : OS.RBS_UNCHECKEDHOT; + } else { // checkbox button + return (dwCheckState == OS.BST_CHECKED) ? OS.CBS_CHECKEDHOT : (dwCheckState == OS.BST_UNCHECKED) ? OS.CBS_UNCHECKEDHOT : OS.CBS_MIXEDHOT; + } + } + + // normal button + if ((style & SWT.RADIO) != 0) { // radio button + return (dwCheckState == OS.BST_CHECKED) ? OS.RBS_CHECKEDNORMAL : OS.RBS_UNCHECKEDNORMAL; + } else { // checkbox button + return (dwCheckState == OS.BST_CHECKED) ? OS.CBS_CHECKEDNORMAL : (dwCheckState == OS.BST_UNCHECKED) ? OS.CBS_UNCHECKEDNORMAL : OS.CBS_MIXEDNORMAL; + } +} + +/* + * Return the width of the bitmap that is drawn in the background for the radio or checkbox. + */ +int getThemeBitmapWidth(int hTheme, int iPartId, int iState) { + BITMAP bm = new BITMAP(); + int [] hBitmap = new int [1]; + OS.GetThemeBitmap(hTheme, iPartId, iState, 0, OS.GBF_DIRECT, hBitmap); + OS.GetObject(hBitmap[0], BITMAP.sizeof, bm); + return bm.bmWidth; +} + } |