diff options
author | Alexandr Miloslavskiy | 2018-11-06 10:26:35 +0000 |
---|---|---|
committer | Niraj Modi | 2018-11-15 11:10:56 +0000 |
commit | 2982c4163ff033b48acfa8f9135083028f1a0900 (patch) | |
tree | 92d7e43412c8bb65d3f50d803d5853bd95a66fe6 | |
parent | 404282c8d749d625cedc905b6b7b3ba457ac6b7e (diff) | |
download | eclipse.platform.swt-2982c4163ff033b48acfa8f9135083028f1a0900.tar.gz eclipse.platform.swt-2982c4163ff033b48acfa8f9135083028f1a0900.tar.xz eclipse.platform.swt-2982c4163ff033b48acfa8f9135083028f1a0900.zip |
Bug 508634 - [Win32] READ_ONLY Combobox does not allow changing background or foreground color
Change internal undocumented state of combobox to draw in a better way
Change-Id: I012a8a8fb4761ed9942d347780b0b9c7e1aca95d
Signed-off-by: Alexandr Miloslavskiy <alexandr.miloslavskiy@syntevo.com>
-rw-r--r-- | bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java index cd8a14ed77..af22df8de4 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Combo.java @@ -67,6 +67,7 @@ public class Combo extends Composite { String [] items = new String [0]; int[] segments; int clearSegmentsCount = 0; + boolean stateFlagsUsable; static final char LTR_MARK = '\u200e'; static final char RTL_MARK = '\u200f'; @@ -105,7 +106,11 @@ public class Combo extends Composite { ComboProc = lpWndClass.lpfnWndProc; } -/** + /* Undocumented values. Remained the same at least between Win7 and Win10 */ + static final int stateFlagsOffset = (C.PTR_SIZEOF == 8) ? 0x68 : 0x54; + static final int stateFlagsFirstPaint = 0x02000000; + + /** * Constructs a new instance of this class given its parent * and a style value describing its behavior and appearance. * <p> @@ -731,6 +736,8 @@ void createHandle () { } state &= ~(CANVAS | THEME_BACKGROUND); + stateFlagsUsable = stateFlagsTest(); + /* Get the text and list window procs */ long /*int*/ hwndText = OS.GetDlgItem (handle, CBID_EDIT); if (hwndText != 0 && EditProc == 0) { @@ -1519,6 +1526,37 @@ public void paste () { OS.SendMessage (handle, OS.WM_PASTE, 0, 0); } +void stateFlagsAdd(int flags) { + final long /*int*/ tagCBoxPtr = OS.GetWindowLongPtr(handle, 0); + final long /*int*/ stateFlagsPtr = tagCBoxPtr + stateFlagsOffset; + + int stateFlags[] = new int[1]; + OS.MoveMemory(stateFlags, stateFlagsPtr, 4); + stateFlags[0] |= flags; + OS.MoveMemory(stateFlagsPtr, stateFlags, 4); +} + +/* + * Verify that undocumented internal data is in expected location. + * The test is performed at creation time, when the value of state flags is predictable. + * For simplicity, only SWT.READ_ONLY combos are handled. + */ +boolean stateFlagsTest() { + final long /*int*/ tagCBoxPtr = OS.GetWindowLongPtr(handle, 0); + final long /*int*/ stateFlagsPtr = tagCBoxPtr + stateFlagsOffset; + + int stateFlags[] = new int[1]; + OS.MoveMemory(stateFlags, stateFlagsPtr, 4); + + /* + * 0x00000002 is unknown + * 0x00002000 is set in WM_NCCREATE + * 0x00004000 means CBS_DROPDOWNLIST (SWT.READ_ONLY) + * 0x02000000 is set in WM_NCCREATE and reset after first WM_PAINT + */ + return (stateFlags[0] == 0x02006002); +} + @Override void register () { super.register (); @@ -2770,6 +2808,36 @@ long /*int*/ windowProc (long /*int*/ hwnd, int msg, long /*int*/ wParam, long / } @Override +LRESULT wmColorChild (long /*int*/ wParam, long /*int*/ lParam) { + LRESULT result = super.wmColorChild(wParam, lParam); + + /* + * CBS_DROPDOWNLIST (SWT.READ_ONLY) comboboxes ignore results of WM_CTLCOLORxxx. + * This prevents SWT from setting custom background / text color. + * In Windows function 'comctl32!ComboBox_InternalUpdateEditWindow' there are two main branches: + * 'DrawThemeText' branch + * Ignores any SetTextColor / SetBkColor. + * Ignores brush returned from WM_CTLCOLORxxx. + * Keeps any background that was painted during WM_CTLCOLORxxx. + * 'ExtTextOut' branch + * Uses pre-selected SetTextColor / SetBkColor. + * Ignores brush returned from WM_CTLCOLORxxx. + * Overwrites background with color in SetBkColor. + * This undocumented hack forces combobox to use 'ExtTextOut' branch. + * The flag is reset after every WM_PAINT, so it's set in every WM_CTLCOLORxxx. + * Since 'ExtTextOut' always paints background, hack is not activated if not needed + * to avoid changes in visual appearance of comboboxes with default colors. + */ + final boolean isReadonly = ((style & SWT.READ_ONLY) != 0); + final boolean isCustomColors = (result != null); + if (isReadonly && isCustomColors && stateFlagsUsable) { + stateFlagsAdd(stateFlagsFirstPaint); + } + + return result; +} + +@Override LRESULT WM_CTLCOLOR (long /*int*/ wParam, long /*int*/ lParam) { return wmColorChild (wParam, lParam); } |