1 |
/******************************************************************************* |
= |
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2000, 2005 IBM Corporation and others. |
|
2 |
* Copyright (c) 2000, 2005 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
|
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
|
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
|
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
|
6 |
* http://www.eclipse.org/legal/epl-v10.html |
7 |
* |
|
7 |
* |
8 |
* Contributors: |
|
8 |
* Contributors: |
9 |
* IBM Corporation - initial API and implementation |
|
9 |
* IBM Corporation - initial API and implementation |
10 |
*******************************************************************************/ |
|
10 |
*******************************************************************************/ |
|
|
<> |
11 |
/******************************************************************************* |
|
|
|
12 |
* Additions/modifications to this source file by Oracle America, Inc. 2011 |
|
|
|
13 |
*******************************************************************************/ |
11 |
|
= |
14 |
|
12 |
#include "ugl_win32.h" |
|
15 |
#include "ugl_win32.h" |
13 |
#include "UGL_Win32_Widget.h" |
|
16 |
#include "UGL_Win32_Widget.h" |
14 |
#include "UGL_win32_display.h" |
|
17 |
#include "UGL_win32_display.h" |
15 |
#include "UGL_Win32_DC.h" |
|
18 |
#include "UGL_Win32_DC.h" |
16 |
|
|
19 |
|
17 |
#include "Widget.h" |
|
20 |
#include "Widget.h" |
18 |
#include "Control.h" |
|
21 |
#include "Control.h" |
19 |
#include "Choice.h" |
|
22 |
#include "Choice.h" |
20 |
#include "Combo.h" |
|
23 |
#include "Combo.h" |
21 |
#include "VerifyHelpers.h" |
|
24 |
#include "VerifyHelpers.h" |
22 |
|
|
25 |
|
23 |
//======================================================================================== |
|
26 |
//======================================================================================== |
24 |
#define CBID_EDIT 1001 |
|
27 |
#define CBID_EDIT 1001 |
25 |
#define CBID_LIST 1000 |
|
28 |
#define CBID_LIST 1000 |
26 |
static UGL_Int _Combo_ExStyle(UGL_Int ugl_style); |
|
29 |
static UGL_Int _Combo_ExStyle(UGL_Int ugl_style); |
27 |
static UGL_Int _Combo_Style(UGL_Int ugl_style); |
|
30 |
static UGL_Int _Combo_Style(UGL_Int ugl_style); |
28 |
void _Dispose_Combo(UGL_Int handle, UGL_Error uglError); |
|
31 |
void _Dispose_Combo(UGL_Int handle, UGL_Error uglError); |
29 |
int _Combo_CTLCOLOR(PUGL_Control parent_control, HDC hdc, PUGL_Control color_control); |
|
32 |
int _Combo_CTLCOLOR(PUGL_Control parent_control, HDC hdc, PUGL_Control color_control); |
30 |
LRESULT _Combo_CommandChild(PUGL_Control ugl_control, WPARAM wParam, HWND hWnd); |
|
33 |
LRESULT _Combo_CommandChild(PUGL_Control ugl_control, WPARAM wParam, HWND hWnd); |
31 |
void _Combo_SetBounds(PUGL_Control ugl_control, LPRECT bounds); |
|
34 |
void _Combo_SetBounds(PUGL_Control ugl_control, LPRECT bounds); |
32 |
|
|
35 |
|
33 |
static LRESULT CALLBACK _Combo_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); |
|
36 |
static LRESULT CALLBACK _Combo_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); |
34 |
void _Combo_GetMinimumSize(UGL_Int handle, POINT *point, UGL_Error uglError); |
|
37 |
void _Combo_GetMinimumSize(UGL_Int handle, POINT *point, UGL_Error uglError); |
35 |
LRESULT CALLBACK _Combo_Text_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); |
|
38 |
LRESULT CALLBACK _Combo_Text_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); |
36 |
LRESULT CALLBACK _Combo_List_Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); |
|
39 |
LRESULT CALLBACK _Combo_List_Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); |
37 |
|
|
40 |
|
38 |
UGL_Boolean _Combo_SendKeyEvent(PUGL_Control control, UGL_Int type, UGL_Char character, UGL_Int keycode, UGL_Int modifiers); |
|
41 |
UGL_Boolean _Combo_SendKeyEvent(PUGL_Control control, UGL_Int type, UGL_Char character, UGL_Int keycode, UGL_Int modifiers); |
39 |
|
|
42 |
|
40 |
UGL_Boolean _Combo_Text_ProcessWmChar(PUGL_Control ugl_control, TCHAR ch); |
|
43 |
UGL_Boolean _Combo_Text_ProcessWmChar(PUGL_Control ugl_control, TCHAR ch); |
41 |
void _Combo_Text_CombineNewString(TCHAR *curStr, TCHAR *newStr, int pos1, int pos2, TCHAR ch); |
|
44 |
void _Combo_Text_CombineNewString(TCHAR *curStr, TCHAR *newStr, int pos1, int pos2, TCHAR ch); |
42 |
UGL_Boolean _Combo_Text_FindAndSelectItem(HWND hwnd, LPCSTR str); |
|
45 |
UGL_Boolean _Combo_Text_FindAndSelectItem(HWND hwnd, LPCSTR str); |
43 |
void _Combo_Text_RestoreText(PUGL_Control ugl_control); |
|
46 |
void _Combo_Text_RestoreText(PUGL_Control ugl_control); |
44 |
void _Combo_Text_SaveText(PUGL_Control ugl_control); |
|
47 |
void _Combo_Text_SaveText(PUGL_Control ugl_control); |
45 |
HWND comboHwnd = NULL; |
+- |
|
|
46 |
//======================================================================================== |
= |
48 |
//======================================================================================== |
47 |
|
|
49 |
|
48 |
void Combo_ReplaceText(UGL_Int handle, UGL_String text, int start, int end, UGL_Error uglError) { |
|
50 |
void Combo_ReplaceText(UGL_Int handle, UGL_String text, int start, int end, UGL_Error uglError) { |
49 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
|
51 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
50 |
HWND textHWnd = GetDlgItem(ugl_combo->hWnd, CBID_EDIT); |
|
52 |
HWND textHWnd = GetDlgItem(ugl_combo->hWnd, CBID_EDIT); |
51 |
|
|
53 |
|
52 |
SendMessage(textHWnd, EM_SETSEL, start, end); |
|
54 |
SendMessage(textHWnd, EM_SETSEL, start, end); |
53 |
SendMessage(textHWnd, EM_SCROLLCARET, 0, 0); |
|
55 |
SendMessage(textHWnd, EM_SCROLLCARET, 0, 0); |
54 |
|
|
56 |
|
55 |
UGL_COMBO(handle)->ignoreChange = TRUE; |
|
57 |
UGL_COMBO(handle)->ignoreChange = TRUE; |
56 |
SendMessage(textHWnd, EM_REPLACESEL, (WPARAM)TRUE, (LPARAM)text); |
|
58 |
SendMessage(textHWnd, EM_REPLACESEL, (WPARAM)TRUE, (LPARAM)text); |
57 |
UGL_COMBO(handle)->ignoreChange = FALSE; |
|
59 |
UGL_COMBO(handle)->ignoreChange = FALSE; |
58 |
} |
|
60 |
} |
59 |
|
|
61 |
|
60 |
//======================================================================================== |
|
62 |
//======================================================================================== |
61 |
|
|
63 |
|
62 |
UGL_String Combo_GetText(UGL_Int handle, UGL_Boolean* shouldFreeResult, UGL_Error uglError) { |
|
64 |
UGL_String Combo_GetText(UGL_Int handle, UGL_Boolean* shouldFreeResult, UGL_Error uglError) { |
63 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
|
65 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
64 |
UGL_String text = NULL; |
|
66 |
UGL_String text = NULL; |
65 |
int length = GetWindowTextLength(ugl_combo->hWnd); |
|
67 |
int length = GetWindowTextLength(ugl_combo->hWnd); |
66 |
|
|
68 |
|
67 |
if (length == 0) { |
|
69 |
if (length == 0) { |
68 |
*shouldFreeResult = FALSE; |
|
70 |
*shouldFreeResult = FALSE; |
69 |
return _T(""); |
|
71 |
return _T(""); |
70 |
} |
|
72 |
} |
71 |
|
|
73 |
|
72 |
text = (UGL_String)calloc(sizeof(TCHAR), length+1); |
|
74 |
text = (UGL_String)calloc(sizeof(TCHAR), length+1); |
73 |
if (text == NULL) { |
|
75 |
if (text == NULL) { |
74 |
Win32Error_SetError(uglError, UGL_ERROR_OUT_OF_MEMORY, _T("Unable to allocate memory for text")); |
|
76 |
Win32Error_SetError(uglError, UGL_ERROR_OUT_OF_MEMORY, _T("Unable to allocate memory for text")); |
75 |
return (UGL_String)NULL; |
|
77 |
return (UGL_String)NULL; |
76 |
} |
|
78 |
} |
77 |
|
|
79 |
|
78 |
GetWindowText(ugl_combo->hWnd, (LPTSTR)text, length + 1); |
|
80 |
GetWindowText(ugl_combo->hWnd, (LPTSTR)text, length + 1); |
79 |
|
|
81 |
|
80 |
*shouldFreeResult = TRUE; |
|
82 |
*shouldFreeResult = TRUE; |
81 |
return text; |
|
83 |
return text; |
82 |
} |
|
84 |
} |
83 |
//======================================================================================== |
|
85 |
//======================================================================================== |
84 |
|
|
86 |
|
85 |
UGL_Int Combo_GetDefaultTextLimit(UGL_Error uglError) { |
|
87 |
UGL_Int Combo_GetDefaultTextLimit(UGL_Error uglError) { |
86 |
OSVERSIONINFO info; |
|
88 |
OSVERSIONINFO info; |
87 |
|
|
89 |
|
88 |
GetVersionEx((LPOSVERSIONINFO)&info); |
|
90 |
GetVersionEx((LPOSVERSIONINFO)&info); |
89 |
return (info.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 0x7FFFFFFF : 0x7FFF; |
|
91 |
return (info.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 0x7FFFFFFF : 0x7FFF; |
90 |
} |
|
92 |
} |
91 |
//======================================================================================== |
|
93 |
//======================================================================================== |
92 |
|
|
94 |
|
93 |
UGL_Int Combo_GetTextHeight(UGL_Int handle, UGL_Error uglError) { |
|
95 |
UGL_Int Combo_GetTextHeight(UGL_Int handle, UGL_Error uglError) { |
94 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
|
96 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
95 |
|
|
97 |
|
96 |
int result = SendMessage(ugl_combo->hWnd, CB_GETITEMHEIGHT, -1, 0); |
|
98 |
int result = SendMessage(ugl_combo->hWnd, CB_GETITEMHEIGHT, -1, 0); |
97 |
if (result == CB_ERR) { |
|
99 |
if (result == CB_ERR) { |
98 |
Win32Error_SetError(uglError, GetLastError(), _T("Unable to get item height")); |
|
100 |
Win32Error_SetError(uglError, GetLastError(), _T("Unable to get item height")); |
99 |
return 0; |
|
101 |
return 0; |
100 |
} |
|
102 |
} |
101 |
|
|
103 |
|
102 |
// why the +6? SWT does it, no other reason... |
|
104 |
// why the +6? SWT does it, no other reason... |
103 |
return result + 6; |
|
105 |
return result + 6; |
104 |
} |
|
106 |
} |
105 |
//======================================================================================== |
|
107 |
//======================================================================================== |
106 |
|
|
108 |
|
107 |
void Combo_SetTextLimit(UGL_Int handle, UGL_Int limit, UGL_Error uglError) { |
|
109 |
void Combo_SetTextLimit(UGL_Int handle, UGL_Int limit, UGL_Error uglError) { |
108 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
|
110 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
109 |
|
|
111 |
|
110 |
if (limit == 0) { |
|
112 |
if (limit == 0) { |
111 |
Win32Error_SetError(uglError, UGL_ERROR_OTHER, _T("Limit can not be 0 for combo")); |
|
113 |
Win32Error_SetError(uglError, UGL_ERROR_OTHER, _T("Limit can not be 0 for combo")); |
112 |
return; |
|
114 |
return; |
113 |
} |
|
115 |
} |
114 |
|
|
116 |
|
115 |
SendMessage(ugl_combo->hWnd, CB_LIMITTEXT, limit, 0); |
|
117 |
SendMessage(ugl_combo->hWnd, CB_LIMITTEXT, limit, 0); |
116 |
} |
|
118 |
} |
117 |
//======================================================================================== |
|
119 |
//======================================================================================== |
118 |
|
|
120 |
|
119 |
UGL_Int Combo_GetItemHeight(UGL_Int handle, UGL_Error uglError) { |
|
121 |
UGL_Int Combo_GetItemHeight(UGL_Int handle, UGL_Error uglError) { |
120 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
|
122 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
121 |
|
|
123 |
|
122 |
int result = SendMessage(ugl_combo->hWnd, CB_GETITEMHEIGHT, 0, 0); |
|
124 |
int result = SendMessage(ugl_combo->hWnd, CB_GETITEMHEIGHT, 0, 0); |
123 |
if (result == CB_ERR) { |
|
125 |
if (result == CB_ERR) { |
124 |
Win32Error_SetError(uglError, GetLastError(), _T("Unable to get item height from combo")); |
|
126 |
Win32Error_SetError(uglError, GetLastError(), _T("Unable to get item height from combo")); |
125 |
return 0; |
|
127 |
return 0; |
126 |
} else { |
|
128 |
} else { |
127 |
return result; |
|
129 |
return result; |
128 |
} |
|
130 |
} |
129 |
} |
|
131 |
} |
130 |
//======================================================================================== |
|
132 |
//======================================================================================== |
131 |
|
|
133 |
|
132 |
void Combo_DeselectItem(UGL_Int handle, UGL_Int index, UGL_Error uglError) { |
|
134 |
void Combo_DeselectItem(UGL_Int handle, UGL_Int index, UGL_Error uglError) { |
133 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
|
135 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
134 |
int selection = SendMessage(ugl_combo->hWnd, CB_GETCURSEL, 0, 0); |
|
136 |
int selection = SendMessage(ugl_combo->hWnd, CB_GETCURSEL, 0, 0); |
135 |
|
|
137 |
|
136 |
if (index != selection) return; |
|
138 |
if (index != selection) return; |
137 |
SendMessage(ugl_combo->hWnd, CB_SETCURSEL, -1, 0); |
|
139 |
SendMessage(ugl_combo->hWnd, CB_SETCURSEL, -1, 0); |
138 |
} |
|
140 |
} |
139 |
//======================================================================================== |
|
141 |
//======================================================================================== |
140 |
|
|
142 |
|
141 |
void Combo_DeselectAllItems(UGL_Int handle, UGL_Error uglError) { |
|
143 |
void Combo_DeselectAllItems(UGL_Int handle, UGL_Error uglError) { |
142 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
|
144 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
143 |
|
|
145 |
|
144 |
SendMessage(ugl_combo->hWnd, CB_SETCURSEL, -1, 0); |
|
146 |
SendMessage(ugl_combo->hWnd, CB_SETCURSEL, -1, 0); |
145 |
} |
|
147 |
} |
146 |
//======================================================================================== |
|
148 |
//======================================================================================== |
147 |
|
|
149 |
|
148 |
void Combo_SetText(UGL_Int handle, UGL_String string, UGL_Error uglError) { |
|
150 |
void Combo_SetText(UGL_Int handle, UGL_String string, UGL_Error uglError) { |
149 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
|
151 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
150 |
|
|
152 |
|
151 |
// this is desired behavior? |
|
153 |
// this is desired behavior? |
152 |
if (((PUGL_Combo)ugl_combo)->is_read_only) { |
|
154 |
if (((PUGL_Combo)ugl_combo)->is_read_only) { |
153 |
//int index = indexOf (string); |
|
155 |
//int index = indexOf (string); |
154 |
//if (index != -1) select (index); |
|
156 |
//if (index != -1) select (index); |
155 |
return; |
|
157 |
return; |
156 |
} |
|
158 |
} |
157 |
|
|
159 |
|
158 |
SetWindowText(ugl_combo->hWnd, string); |
|
160 |
SetWindowText(ugl_combo->hWnd, string); |
159 |
} |
|
161 |
} |
160 |
//======================================================================================== |
|
162 |
//======================================================================================== |
161 |
|
|
163 |
|
162 |
void Combo_SetOrientation(UGL_Int handle, UGL_Int orientation, UGL_Error uglError) { |
|
164 |
void Combo_SetOrientation(UGL_Int handle, UGL_Int orientation, UGL_Error uglError) { |
163 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
|
165 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
164 |
|
|
166 |
|
165 |
#ifdef _WIN32_WCE |
|
167 |
#ifdef _WIN32_WCE |
166 |
return; |
|
168 |
return; |
167 |
#else |
|
169 |
#else |
168 |
//if ((OS.WIN32_MAJOR << 16 | OS.WIN32_MINOR) < (4 << 16 | 10)) return; |
|
170 |
//if ((OS.WIN32_MAJOR << 16 | OS.WIN32_MINOR) < (4 << 16 | 10)) return; |
169 |
int flags = UGL_STYLE_LEFT_TO_RIGHT | UGL_STYLE_RIGHT_TO_LEFT; |
|
171 |
int flags = UGL_STYLE_LEFT_TO_RIGHT | UGL_STYLE_RIGHT_TO_LEFT; |
170 |
int bits = 0; |
|
172 |
int bits = 0; |
171 |
HWND hwndList, hwndText, hwnd; |
|
173 |
HWND hwndList, hwndText, hwnd; |
172 |
|
|
174 |
|
173 |
hwnd = UGL_CONTROL(ugl_combo)->hWnd; |
|
175 |
hwnd = UGL_CONTROL(ugl_combo)->hWnd; |
174 |
if ((orientation & flags) == 0 || (orientation & flags) == flags) return; |
|
176 |
if ((orientation & flags) == 0 || (orientation & flags) == flags) return; |
175 |
UGL_WIDGET(ugl_combo)->ugl_style &= ~flags; |
|
177 |
UGL_WIDGET(ugl_combo)->ugl_style &= ~flags; |
176 |
UGL_WIDGET(ugl_combo)->ugl_style |= orientation & flags; |
|
178 |
UGL_WIDGET(ugl_combo)->ugl_style |= orientation & flags; |
177 |
|
|
179 |
|
178 |
bits = GetWindowLong(hwnd, GWL_EXSTYLE); |
|
180 |
bits = GetWindowLong(hwnd, GWL_EXSTYLE); |
179 |
if (IS_FLAG_SET(orientation, UGL_STYLE_RIGHT_TO_LEFT)) { |
|
181 |
if (IS_FLAG_SET(orientation, UGL_STYLE_RIGHT_TO_LEFT)) { |
180 |
//style |= SWT.MIRRORED; |
|
182 |
//style |= SWT.MIRRORED; |
181 |
bits |= WS_EX_LAYOUTRTL; |
|
183 |
bits |= WS_EX_LAYOUTRTL; |
182 |
} else { |
|
184 |
} else { |
183 |
//style &= ~SWT.MIRRORED; |
|
185 |
//style &= ~SWT.MIRRORED; |
184 |
bits &= ~WS_EX_LAYOUTRTL; |
|
186 |
bits &= ~WS_EX_LAYOUTRTL; |
185 |
} |
|
187 |
} |
186 |
|
|
188 |
|
187 |
SetWindowLong(hwnd, GWL_EXSTYLE, bits); |
|
189 |
SetWindowLong(hwnd, GWL_EXSTYLE, bits); |
188 |
|
|
190 |
|
189 |
hwndList = GetDlgItem(hwnd, CBID_LIST); |
|
191 |
hwndList = GetDlgItem(hwnd, CBID_LIST); |
190 |
hwndText = GetDlgItem(hwnd, CBID_EDIT); |
|
192 |
hwndText = GetDlgItem(hwnd, CBID_EDIT); |
191 |
|
|
193 |
|
192 |
if (hwndText != NULL) { |
|
194 |
if (hwndText != NULL) { |
193 |
int bits_exstyle = GetWindowLong(hwndText, GWL_EXSTYLE); |
|
195 |
int bits_exstyle = GetWindowLong(hwndText, GWL_EXSTYLE); |
194 |
int bits_style = GetWindowLong(hwndText, GWL_STYLE); |
|
196 |
int bits_style = GetWindowLong(hwndText, GWL_STYLE); |
195 |
if (IS_FLAG_SET(orientation, UGL_STYLE_RIGHT_TO_LEFT)) { |
|
197 |
if (IS_FLAG_SET(orientation, UGL_STYLE_RIGHT_TO_LEFT)) { |
196 |
bits_exstyle |= WS_EX_RIGHT | WS_EX_RTLREADING; |
|
198 |
bits_exstyle |= WS_EX_RIGHT | WS_EX_RTLREADING; |
197 |
bits_style |= ES_RIGHT; |
|
199 |
bits_style |= ES_RIGHT; |
198 |
} else { |
|
200 |
} else { |
199 |
bits_exstyle &= ~(WS_EX_RIGHT | WS_EX_RTLREADING); |
|
201 |
bits_exstyle &= ~(WS_EX_RIGHT | WS_EX_RTLREADING); |
200 |
bits_style &= ~ES_RIGHT; |
|
202 |
bits_style &= ~ES_RIGHT; |
201 |
} |
|
203 |
} |
202 |
SetWindowLong(hwndText, GWL_EXSTYLE, bits_exstyle); |
|
204 |
SetWindowLong(hwndText, GWL_EXSTYLE, bits_exstyle); |
203 |
SetWindowLong(hwndText, GWL_STYLE, bits_style); |
|
205 |
SetWindowLong(hwndText, GWL_STYLE, bits_style); |
204 |
|
|
206 |
|
205 |
/* |
|
207 |
/* |
206 |
* Bug in Windows. For some reason, the single line text field |
|
208 |
* Bug in Windows. For some reason, the single line text field |
207 |
* portion of the combo box does not redraw to reflect the new |
|
209 |
* portion of the combo box does not redraw to reflect the new |
208 |
* style bits. The fix is to force the widget to be resized by |
|
210 |
* style bits. The fix is to force the widget to be resized by |
209 |
* temporarily shrinking and then growing the width and height. |
|
211 |
* temporarily shrinking and then growing the width and height. |
210 |
*/ |
|
212 |
*/ |
211 |
|
|
213 |
|
212 |
InvalidateRect(hwndText, NULL, TRUE); |
|
214 |
InvalidateRect(hwndText, NULL, TRUE); |
213 |
//RECT rect = new RECT (); |
|
215 |
//RECT rect = new RECT (); |
214 |
//OS.GetWindowRect (hwndText, rect); |
|
216 |
//OS.GetWindowRect (hwndText, rect); |
215 |
//int width = rect.right - rect.left, height = rect.bottom - rect.top; |
|
217 |
//int width = rect.right - rect.left, height = rect.bottom - rect.top; |
216 |
//OS.GetWindowRect (handle, rect); |
|
218 |
//OS.GetWindowRect (handle, rect); |
217 |
//int widthCombo = rect.right - rect.left, heightCombo = rect.bottom - rect.top; |
|
219 |
//int widthCombo = rect.right - rect.left, heightCombo = rect.bottom - rect.top; |
218 |
//int uFlags = OS.SWP_NOMOVE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE; |
|
220 |
//int uFlags = OS.SWP_NOMOVE | OS.SWP_NOZORDER | OS.SWP_NOACTIVATE; |
219 |
//SetWindowPos (hwndText, 0, 0, 0, width - 1, height - 1, uFlags); |
|
221 |
//SetWindowPos (hwndText, 0, 0, 0, width - 1, height - 1, uFlags); |
220 |
//SetWindowPos (handle, 0, 0, 0, widthCombo - 1, heightCombo - 1, uFlags); |
|
222 |
//SetWindowPos (handle, 0, 0, 0, widthCombo - 1, heightCombo - 1, uFlags); |
221 |
//SetWindowPos (hwndText, 0, 0, 0, width, height, uFlags); |
|
223 |
//SetWindowPos (hwndText, 0, 0, 0, width, height, uFlags); |
222 |
//SetWindowPos (handle, 0, 0, 0, widthCombo, heightCombo, uFlags); |
|
224 |
//SetWindowPos (handle, 0, 0, 0, widthCombo, heightCombo, uFlags); |
223 |
//OS.InvalidateRect (handle, null, true); |
|
225 |
//OS.InvalidateRect (handle, null, true); |
224 |
} |
|
226 |
} |
225 |
if (hwndList != NULL) { |
|
227 |
if (hwndList != NULL) { |
226 |
int bits_exstyle = GetWindowLong(hwndList, GWL_EXSTYLE); |
|
228 |
int bits_exstyle = GetWindowLong(hwndList, GWL_EXSTYLE); |
227 |
if (IS_FLAG_SET(orientation, UGL_STYLE_RIGHT_TO_LEFT)) { |
|
229 |
if (IS_FLAG_SET(orientation, UGL_STYLE_RIGHT_TO_LEFT)) { |
228 |
bits_exstyle |= WS_EX_LAYOUTRTL; |
|
230 |
bits_exstyle |= WS_EX_LAYOUTRTL; |
229 |
} else { |
|
231 |
} else { |
230 |
bits_exstyle &= ~WS_EX_LAYOUTRTL; |
|
232 |
bits_exstyle &= ~WS_EX_LAYOUTRTL; |
231 |
} |
|
233 |
} |
232 |
SetWindowLong(hwndList, GWL_EXSTYLE, bits_exstyle); |
|
234 |
SetWindowLong(hwndList, GWL_EXSTYLE, bits_exstyle); |
233 |
} |
|
235 |
} |
234 |
#endif // defined _WIN32_WCE |
|
236 |
#endif // defined _WIN32_WCE |
235 |
} |
|
237 |
} |
236 |
//======================================================================================== |
|
238 |
//======================================================================================== |
237 |
|
|
239 |
|
238 |
void Combo_SetTextSelection(UGL_Int handle, UGL_Int start, UGL_Int end, UGL_Error uglError) { |
|
240 |
void Combo_SetTextSelection(UGL_Int handle, UGL_Int start, UGL_Int end, UGL_Error uglError) { |
239 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
|
241 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
240 |
|
|
242 |
|
241 |
int bits = start | (end << 16); |
|
243 |
int bits = start | (end << 16); |
242 |
SendMessage(UGL_CONTROL(ugl_combo)->hWnd, CB_SETEDITSEL, 0, bits); |
|
244 |
SendMessage(UGL_CONTROL(ugl_combo)->hWnd, CB_SETEDITSEL, 0, bits); |
243 |
} |
|
245 |
} |
244 |
//======================================================================================== |
|
246 |
//======================================================================================== |
245 |
|
|
247 |
|
246 |
UGL_Int Combo_New(UGL_Int parentHandle, UGL_Int ugl_style, UGL_Error uglError) { |
|
248 |
UGL_Int Combo_New(UGL_Int parentHandle, UGL_Int ugl_style, UGL_Error uglError) { |
247 |
return _Combo_New(parentHandle, ugl_style, uglError); |
|
249 |
return _Combo_New(parentHandle, ugl_style, uglError); |
248 |
} |
|
250 |
} |
249 |
|
|
251 |
|
250 |
UGL_Int _Combo_New(UGL_Int parentHandle, UGL_Int ugl_style, UGL_Error uglError) { |
|
252 |
UGL_Int _Combo_New(UGL_Int parentHandle, UGL_Int ugl_style, UGL_Error uglError) { |
251 |
int style = _Combo_Style(ugl_style); |
|
253 |
int style = _Combo_Style(ugl_style); |
252 |
int extended_style = _Combo_ExStyle(ugl_style); |
|
254 |
int extended_style = _Combo_ExStyle(ugl_style); |
253 |
HWND textHWnd, listHWnd; |
|
255 |
HWND textHWnd, listHWnd; |
254 |
|
|
256 |
|
255 |
PUGL_Control ugl_control = _Control_New(_T("COMBOBOX"), sizeof(UGL_Combo), _Combo_Proc, |
|
257 |
PUGL_Control ugl_control = _Control_New(_T("COMBOBOX"), sizeof(UGL_Combo), _Combo_Proc, |
256 |
parentHandle, ugl_style, style, extended_style, uglError); |
|
258 |
parentHandle, ugl_style, style, extended_style, uglError); |
257 |
|
|
259 |
|
258 |
// TODO check return conditions! |
|
260 |
// TODO check return conditions! |
259 |
UGL_COMBO(ugl_control)->is_read_only = (IS_FLAG_SET(ugl_style, UGL_STYLE_READ_ONLY)); |
|
261 |
UGL_COMBO(ugl_control)->is_read_only = (IS_FLAG_SET(ugl_style, UGL_STYLE_READ_ONLY)); |
260 |
|
|
262 |
|
261 |
UGL_WIDGET(ugl_control)->widget_dispose = _Dispose_Combo; |
|
263 |
UGL_WIDGET(ugl_control)->widget_dispose = _Dispose_Combo; |
262 |
ugl_control->sendKeyEvent = _Combo_SendKeyEvent; |
|
264 |
ugl_control->sendKeyEvent = _Combo_SendKeyEvent; |
263 |
|
|
265 |
|
264 |
textHWnd = GetDlgItem(ugl_control->hWnd, CBID_EDIT); |
|
266 |
textHWnd = GetDlgItem(ugl_control->hWnd, CBID_EDIT); |
265 |
listHWnd = GetDlgItem(ugl_control->hWnd, CBID_LIST); |
|
267 |
listHWnd = GetDlgItem(ugl_control->hWnd, CBID_LIST); |
266 |
|
|
268 |
|
267 |
if (textHWnd != NULL) { |
|
269 |
if (textHWnd != NULL) { |
268 |
SetWindowLong(textHWnd, GWL_USERDATA, (LONG)ugl_control); |
|
270 |
SetWindowLong(textHWnd, GWL_USERDATA, (LONG)ugl_control); |
269 |
UGL_COMBO(ugl_control)->textProc = (WNDPROC)GetWindowLong(textHWnd, GWL_WNDPROC); |
|
271 |
UGL_COMBO(ugl_control)->textProc = (WNDPROC)GetWindowLong(textHWnd, GWL_WNDPROC); |
270 |
SetWindowLong(textHWnd, GWL_WNDPROC, (LONG)(_Combo_Text_Proc)); |
|
272 |
SetWindowLong(textHWnd, GWL_WNDPROC, (LONG)(_Combo_Text_Proc)); |
271 |
} |
|
273 |
} |
272 |
|
|
274 |
|
273 |
if (listHWnd != NULL) { |
|
275 |
if (listHWnd != NULL) { |
274 |
/* |
|
276 |
/* |
275 |
* listHWnd is almost always NULL |
|
277 |
* listHWnd is almost always NULL |
276 |
*/ |
|
278 |
*/ |
277 |
SetWindowLong(listHWnd, GWL_USERDATA, (LONG)ugl_control); |
|
279 |
SetWindowLong(listHWnd, GWL_USERDATA, (LONG)ugl_control); |
278 |
UGL_COMBO(ugl_control)->listProc = (WNDPROC)GetWindowLong(listHWnd, GWL_WNDPROC); |
|
280 |
UGL_COMBO(ugl_control)->listProc = (WNDPROC)GetWindowLong(listHWnd, GWL_WNDPROC); |
279 |
} |
|
281 |
} |
280 |
|
|
282 |
|
281 |
/* |
|
283 |
/* |
282 |
* We default to 7 for PPro to mimic the JDK. SWT prefers 5, but it isn't spec'd. |
|
284 |
* We default to 7 for PPro to mimic the JDK. SWT prefers 5, but it isn't spec'd. |
283 |
*/ |
|
285 |
*/ |
284 |
UGL_COMBO(ugl_control)->visibleItems = 7; |
|
286 |
UGL_COMBO(ugl_control)->visibleItems = 7; |
285 |
|
|
287 |
|
286 |
return (UGL_Int)ugl_control; |
|
288 |
return (UGL_Int)ugl_control; |
287 |
} |
|
289 |
} |
288 |
//======================================================================================== |
|
290 |
//======================================================================================== |
289 |
|
|
291 |
|
290 |
void Combo_GetTextSelection(UGL_Int handle, UGL_Int* returnX, UGL_Int* returnY, UGL_Error uglError) { |
|
292 |
void Combo_GetTextSelection(UGL_Int handle, UGL_Int* returnX, UGL_Int* returnY, UGL_Error uglError) { |
291 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
|
293 |
PUGL_Control ugl_combo = (PUGL_Control)handle; |
292 |
|
|
294 |
|
293 |
//if ((style & SWT.DROP_DOWN) != 0 && (style & SWT.READ_ONLY) != 0) { |
|
295 |
//if ((style & SWT.DROP_DOWN) != 0 && (style & SWT.READ_ONLY) != 0) { |
294 |
if (((PUGL_Combo)ugl_combo)->is_read_only) { |
|
296 |
if (((PUGL_Combo)ugl_combo)->is_read_only) { |
295 |
*returnX = 0; |
|
297 |
*returnX = 0; |
296 |
*returnY = GetWindowTextLength(ugl_combo->hWnd); |
|
298 |
*returnY = GetWindowTextLength(ugl_combo->hWnd); |
297 |
} |
|
299 |
} |
298 |
|
|
300 |
|
299 |
SendMessage(ugl_combo->hWnd, CB_GETEDITSEL, (WPARAM)returnX, (LPARAM)returnY); |
|
301 |
SendMessage(ugl_combo->hWnd, CB_GETEDITSEL, (WPARAM)returnX, (LPARAM)returnY); |
300 |
} |
|
302 |
} |
301 |
//======================================================================================== |
|
303 |
//======================================================================================== |
302 |
|
|
304 |
|
303 |
void Combo_SetItem(UGL_Int handle, UGL_String string, UGL_Int index, UGL_Error uglError) { |
|
305 |
void Combo_SetItem(UGL_Int handle, UGL_String string, UGL_Int index, UGL_Error uglError) { |
304 |
Choice_RemoveItem(handle, index, uglError); |
|
306 |
Choice_RemoveItem(handle, index, uglError); |
305 |
Choice_AddItem(handle, string, index, uglError); |
|
307 |
Choice_AddItem(handle, string, index, uglError); |
306 |
} |
|
308 |
} |
307 |
//======================================================================================== |
|
309 |
//======================================================================================== |
308 |
|
|
310 |
|
309 |
UGL_Int Combo_GetVisibleItemCount(UGL_Int handle, UGL_Error uglError) { |
|
311 |
UGL_Int Combo_GetVisibleItemCount(UGL_Int handle, UGL_Error uglError) { |
310 |
PUGL_Combo ugl_control = UGL_COMBO(handle); |
|
312 |
PUGL_Combo ugl_control = UGL_COMBO(handle); |
311 |
return ugl_control->visibleItems; |
|
313 |
return ugl_control->visibleItems; |
312 |
|
|
314 |
|
313 |
} |
|
315 |
} |
314 |
//======================================================================================== |
|
316 |
//======================================================================================== |
315 |
|
|
317 |
|
316 |
void Combo_SetVisibleItemCount(UGL_Int handle, UGL_Int count, UGL_Error uglError) { |
|
318 |
void Combo_SetVisibleItemCount(UGL_Int handle, UGL_Int count, UGL_Error uglError) { |
317 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
|
319 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
318 |
PUGL_Control ugl_control = (PUGL_Control)ugl_combo; |
|
320 |
PUGL_Control ugl_control = (PUGL_Control)ugl_combo; |
319 |
int numItems = SendMessage(ugl_control->hWnd, CB_GETCOUNT, 0, 0); |
|
321 |
int numItems = SendMessage(ugl_control->hWnd, CB_GETCOUNT, 0, 0); |
320 |
if (count < 0) return; //error |
|
322 |
if (count < 0) return; //error |
321 |
ugl_combo->visibleItems = count; //don't care if it's greater than numItems and don't have to repaint |
|
323 |
ugl_combo->visibleItems = count; //don't care if it's greater than numItems and don't have to repaint |
322 |
|
|
324 |
|
323 |
} |
|
325 |
} |
324 |
//======================================================================================== |
|
326 |
//======================================================================================== |
325 |
|
|
327 |
|
326 |
UGL_Int _Combo_Style(UGL_Int ugl_style) { |
|
328 |
UGL_Int _Combo_Style(UGL_Int ugl_style) { |
327 |
int bits = _Control_Style(ugl_style); |
|
329 |
int bits = _Control_Style(ugl_style); |
328 |
|
|
330 |
|
329 |
bits |= CBS_AUTOHSCROLL | CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP; |
|
331 |
bits |= CBS_AUTOHSCROLL | CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP; |
330 |
|
|
332 |
|
331 |
//if (IS_FLAG_SET(ugl_style, UGL_STYLE_SIMPLE)) return bits | CBS_SIMPLE; |
|
333 |
//if (IS_FLAG_SET(ugl_style, UGL_STYLE_SIMPLE)) return bits | CBS_SIMPLE; |
332 |
if (IS_FLAG_SET(ugl_style, UGL_STYLE_READ_ONLY)) return bits | CBS_DROPDOWNLIST; |
|
334 |
if (IS_FLAG_SET(ugl_style, UGL_STYLE_READ_ONLY)) return bits | CBS_DROPDOWNLIST; |
333 |
return bits | CBS_DROPDOWN; |
|
335 |
return bits | CBS_DROPDOWN; |
334 |
} |
|
336 |
} |
335 |
//======================================================================================== |
|
337 |
//======================================================================================== |
336 |
|
|
338 |
|
337 |
UGL_Int _Combo_ExStyle(UGL_Int ugl_style) { |
|
339 |
UGL_Int _Combo_ExStyle(UGL_Int ugl_style) { |
338 |
int bits = 0; |
|
340 |
int bits = 0; |
339 |
return bits; |
|
341 |
return bits; |
340 |
} |
|
342 |
} |
341 |
//======================================================================================= |
|
343 |
//======================================================================================= |
342 |
|
|
344 |
|
343 |
LRESULT CALLBACK _Combo_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { |
|
345 |
LRESULT CALLBACK _Combo_Proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { |
344 |
PUGL_Combo ugl_combo = (PUGL_Combo)GetWindowLong(hwnd, GWL_USERDATA); |
|
346 |
PUGL_Combo ugl_combo = (PUGL_Combo)GetWindowLong(hwnd, GWL_USERDATA); |
345 |
comboHwnd = hwnd; |
+- |
|
|
346 |
switch (message) { |
= |
347 |
switch (message) { |
347 |
case WM_CTLCOLOREDIT: |
|
348 |
case WM_CTLCOLOREDIT: |
348 |
case WM_CTLCOLORLISTBOX: { |
|
349 |
case WM_CTLCOLORLISTBOX: { |
349 |
HWND color_widget_hWnd = (HWND)lParam; |
|
350 |
HWND color_widget_hWnd = (HWND)lParam; |
350 |
PUGL_Control color_widget = (PUGL_Control)GetWindowLong(color_widget_hWnd, GWL_USERDATA); |
|
351 |
PUGL_Control color_widget = (PUGL_Control)GetWindowLong(color_widget_hWnd, GWL_USERDATA); |
351 |
PUGL_Control parent_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
|
352 |
PUGL_Control parent_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
352 |
if (color_widget == NULL) { |
|
353 |
if (color_widget == NULL) { |
353 |
return _Combo_CTLCOLOR(parent_control, (HDC)wParam, color_widget); |
|
354 |
return _Combo_CTLCOLOR(parent_control, (HDC)wParam, color_widget); |
354 |
} |
|
355 |
} |
355 |
} break; |
|
356 |
} break; |
356 |
case UI_GET_MINIMUM_SIZE: { |
|
357 |
case UI_GET_MINIMUM_SIZE: { |
357 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
|
358 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
358 |
UGL_Int handle = (UGL_Int)ugl_control; |
|
359 |
UGL_Int handle = (UGL_Int)ugl_control; |
359 |
POINT* point = (POINT*)wParam; |
|
360 |
POINT* point = (POINT*)wParam; |
360 |
_Combo_GetMinimumSize(handle, point, (UGL_Error)lParam); |
|
361 |
_Combo_GetMinimumSize(handle, point, (UGL_Error)lParam); |
361 |
return 0; |
|
362 |
return 0; |
362 |
} break; |
|
363 |
} break; |
363 |
case UI_COMMAND_CHILD: { |
|
364 |
case UI_COMMAND_CHILD: { |
364 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
|
365 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
365 |
return _Combo_CommandChild(ugl_control, wParam, hwnd); |
|
366 |
return _Combo_CommandChild(ugl_control, wParam, hwnd); |
366 |
} break; |
|
367 |
} break; |
367 |
case UI_SET_BOUNDS: { |
|
368 |
case UI_SET_BOUNDS: { |
368 |
/* |
|
369 |
/* |
369 |
* What's going on here is that when we call SetWindowPos() on a Combo, |
|
370 |
* What's going on here is that when we call SetWindowPos() on a Combo, |
370 |
* Windows takes those bounds and constrains the whole Combo, including the |
|
371 |
* Windows takes those bounds and constrains the whole Combo, including the |
371 |
* drop-down list to them. So if we pass along the size that we want for the |
|
372 |
* drop-down list to them. So if we pass along the size that we want for the |
372 |
* 'minimized' Combo, then it will be useless because the drop-down list will |
|
373 |
* 'minimized' Combo, then it will be useless because the drop-down list will |
373 |
* never be visible because it will go outside of the bounds we're giving to |
|
374 |
* never be visible because it will go outside of the bounds we're giving to |
374 |
* Windows. |
|
375 |
* Windows. |
375 |
* The fix is to return the minimum size of an un-expanded Combo box in |
|
376 |
* The fix is to return the minimum size of an un-expanded Combo box in |
376 |
* _Combo_GetMinimumSize(), but to always override the height passed to |
|
377 |
* _Combo_GetMinimumSize(), but to always override the height passed to |
377 |
* SetBounds and set it to the size necessary to show the elements of the list. |
|
378 |
* SetBounds and set it to the size necessary to show the elements of the list. |
378 |
* This way, the list is expandable, but the layouts to think that the Combo |
|
379 |
* This way, the list is expandable, but the layouts to think that the Combo |
379 |
* is the size of the text plus the list. |
|
380 |
* is the size of the text plus the list. |
380 |
*/ |
|
381 |
*/ |
381 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
|
382 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
382 |
UGL_Int handle = (UGL_Int)ugl_control; |
|
383 |
UGL_Int handle = (UGL_Int)ugl_control; |
383 |
LPRECT bounds = (LPRECT)wParam; |
|
384 |
LPRECT bounds = (LPRECT)wParam; |
384 |
_Combo_SetBounds(ugl_control, bounds); |
|
385 |
_Combo_SetBounds(ugl_control, bounds); |
385 |
|
|
386 |
|
386 |
} break; //we want to let this pass through to ultimately go through _Control_SetBounds |
|
387 |
} break; //we want to let this pass through to ultimately go through _Control_SetBounds |
387 |
case WM_KILLFOCUS: { |
|
388 |
case WM_KILLFOCUS: { |
388 |
/* |
|
389 |
/* |
389 |
* When _Control_ForceFocus() is called on a Combo, the native call to |
|
390 |
* When _Control_ForceFocus() is called on a Combo, the native call to |
390 |
* setFocus() sends a WM_SETFOCUS message to the combo, and it immediately |
|
391 |
* setFocus() sends a WM_SETFOCUS message to the combo, and it immediately |
391 |
* bounces the focus to the text component, which causes a WM_KILLFOCUS message |
|
392 |
* bounces the focus to the text component, which causes a WM_KILLFOCUS message |
392 |
* to be sent to the Combo and a WM_SETFOCUS to go to the text component. |
|
393 |
* to be sent to the Combo and a WM_SETFOCUS to go to the text component. |
393 |
* This results in three focus callbacks reported by the combo in java: |
|
394 |
* This results in three focus callbacks reported by the combo in java: |
394 |
* (focus in, focus out, focus in). |
|
395 |
* (focus in, focus out, focus in). |
395 |
* So here and in WM_SETFOCUS, we suppress the callbacks for the first two messages |
|
396 |
* So here and in WM_SETFOCUS, we suppress the callbacks for the first two messages |
396 |
* using the fact that the WPARAM parameter is the HWND of the window gaining or |
|
397 |
* using the fact that the WPARAM parameter is the HWND of the window gaining or |
397 |
* losing focus (gaining on a WM_KILLFOCUS, losing on a WM_SETFOCUS) |
|
398 |
* losing focus (gaining on a WM_KILLFOCUS, losing on a WM_SETFOCUS) |
398 |
*/ |
|
399 |
*/ |
399 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
|
400 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hwnd, GWL_USERDATA); |
400 |
HWND lastFocusWind = (HWND)wParam; |
|
401 |
HWND lastFocusWind = (HWND)wParam; |
401 |
PUGL_Control lastFocusControl = (PUGL_Control)GetWindowLong(lastFocusWind, GWL_USERDATA); |
|
402 |
PUGL_Control lastFocusControl = (PUGL_Control)GetWindowLong(lastFocusWind, GWL_USERDATA); |
402 |
UGL_Boolean ignoreFocusEvent = (ugl_control == lastFocusControl); |
|
403 |
UGL_Boolean ignoreFocusEvent = (ugl_control == lastFocusControl); |
403 |
if (ignoreFocusEvent) { |
|
404 |
if (ignoreFocusEvent) { |
404 |
if (ugl_control->widgetProc != NULL) return CallWindowProc(ugl_control->widgetProc, hwnd, message, wParam, lParam); |
|
405 |
if (ugl_control->widgetProc != NULL) return CallWindowProc(ugl_control->widgetProc, hwnd, message, wParam, lParam); |
405 |
else return DefWindowProc(hwnd, message, wParam, lParam); |
|
406 |
else return DefWindowProc(hwnd, message, wParam, lParam); |
406 |
} |
|
407 |
} |
407 |
} break; |
|
408 |
} break; |
408 |
case WM_SETFOCUS: { |
|
409 |
case WM_SETFOCUS: { |
409 |
PUGL_Control ugl_control = (PUGL_Control)ugl_combo; |
|
410 |
PUGL_Control ugl_control = (PUGL_Control)ugl_combo; |
410 |
HWND lastFocusWind = (HWND)wParam; |
|
411 |
HWND lastFocusWind = (HWND)wParam; |
411 |
int selection, count, style; |
|
412 |
int selection, count, style; |
412 |
PUGL_Control lastFocusControl = (PUGL_Control)GetWindowLong(lastFocusWind, GWL_USERDATA); |
|
413 |
PUGL_Control lastFocusControl = (PUGL_Control)GetWindowLong(lastFocusWind, GWL_USERDATA); |
413 |
UGL_Boolean ignoreFocusEvent = (ugl_control == lastFocusControl); |
|
414 |
UGL_Boolean ignoreFocusEvent = (ugl_control == lastFocusControl); |
414 |
if (ignoreFocusEvent) { |
|
415 |
if (ignoreFocusEvent) { |
415 |
if (ugl_control->widgetProc != NULL) return CallWindowProc(ugl_control->widgetProc, hwnd, message, wParam, lParam); |
|
416 |
if (ugl_control->widgetProc != NULL) return CallWindowProc(ugl_control->widgetProc, hwnd, message, wParam, lParam); |
416 |
else return DefWindowProc(hwnd, message, wParam, lParam); |
|
417 |
else return DefWindowProc(hwnd, message, wParam, lParam); |
417 |
} |
|
418 |
} |
418 |
|
|
419 |
|
419 |
//Fot read-only combo, while combo is focused, to select the first item if it existes and nothing was selected before. |
|
420 |
//Fot read-only combo, while combo is focused, to select the first item if it existes and nothing was selected before. |
420 |
style = GetWindowLong(ugl_control->hWnd, GWL_STYLE); |
|
421 |
style = GetWindowLong(ugl_control->hWnd, GWL_STYLE); |
421 |
if (IS_FLAG_SET(style, CBS_DROPDOWNLIST)) { |
|
422 |
if (IS_FLAG_SET(style, CBS_DROPDOWNLIST)) { |
422 |
count = SendMessage(ugl_control->hWnd, CB_GETCOUNT, 0, 0); |
|
423 |
count = SendMessage(ugl_control->hWnd, CB_GETCOUNT, 0, 0); |
423 |
if (count > 1) { |
|
424 |
if (count > 1) { |
424 |
selection = SendMessage(ugl_control->hWnd, CB_GETCURSEL, 0, 0); |
|
425 |
selection = SendMessage(ugl_control->hWnd, CB_GETCURSEL, 0, 0); |
425 |
if (selection < 0) |
|
426 |
if (selection < 0) |
426 |
SendMessage(ugl_control->hWnd, CB_SETCURSEL, 0, 0); |
|
427 |
SendMessage(ugl_control->hWnd, CB_SETCURSEL, 0, 0); |
427 |
} |
|
428 |
} |
428 |
} |
|
429 |
} |
429 |
|
|
430 |
|
430 |
} break; |
|
431 |
} break; |
431 |
|
|
432 |
|
432 |
} |
|
433 |
} |
433 |
return _Control_Proc(hwnd, message, wParam, lParam); |
|
434 |
return _Control_Proc(hwnd, message, wParam, lParam); |
434 |
} |
|
435 |
} |
435 |
|
|
436 |
|
436 |
//======================================================================================== |
|
437 |
//======================================================================================== |
437 |
|
|
438 |
|
438 |
void _Combo_SetBounds(PUGL_Control ugl_control, LPRECT bounds){ |
|
439 |
void _Combo_SetBounds(PUGL_Control ugl_control, LPRECT bounds){ |
439 |
/* |
|
440 |
/* |
440 |
* The height should be the height of an item times the user-requested number of |
|
441 |
* The height should be the height of an item times the user-requested number of |
441 |
* visible items. If that number exceeds the actual number of items in Combo, we |
|
442 |
* visible items. If that number exceeds the actual number of items in Combo, we |
442 |
* still make the Combo this size and Windows fills up the difference with white space. |
|
443 |
* still make the Combo this size and Windows fills up the difference with white space. |
443 |
*/ |
|
444 |
*/ |
444 |
HWND hwnd = ugl_control->hWnd; |
|
445 |
HWND hwnd = ugl_control->hWnd; |
445 |
UGL_Int height = SendMessage(hwnd, CB_GETITEMHEIGHT, 1, 0); |
|
446 |
UGL_Int height = SendMessage(hwnd, CB_GETITEMHEIGHT, 1, 0); |
446 |
int visibleNum = ((PUGL_Combo)ugl_control)->visibleItems; |
|
447 |
int visibleNum = ((PUGL_Combo)ugl_control)->visibleItems; |
447 |
height = height * visibleNum; |
|
448 |
height = height * visibleNum; |
448 |
bounds->bottom = bounds->bottom + height + 2; |
|
449 |
bounds->bottom = bounds->bottom + height + 2; |
449 |
} |
|
450 |
} |
450 |
|
|
451 |
|
451 |
UGL_Boolean _Combo_SendKeyEvent(PUGL_Control control, UGL_Int type, UGL_Char character, UGL_Int keycode, UGL_Int modifiers) { |
|
452 |
UGL_Boolean _Combo_SendKeyEvent(PUGL_Control control, UGL_Int type, UGL_Char character, UGL_Int keycode, UGL_Int modifiers) { |
452 |
return VerifyHelper_SendKeyEvent(control, GetDlgItem(control->hWnd, CBID_EDIT), type, character, keycode, modifiers); |
|
453 |
return VerifyHelper_SendKeyEvent(control, GetDlgItem(control->hWnd, CBID_EDIT), type, character, keycode, modifiers); |
453 |
} |
|
454 |
} |
454 |
|
|
455 |
|
455 |
//======================================================================================== |
|
456 |
//======================================================================================== |
456 |
LRESULT CALLBACK _Combo_List_Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { |
|
457 |
LRESULT CALLBACK _Combo_List_Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { |
457 |
/* |
|
458 |
/* |
458 |
* I don't think we ever get a handle on the List Proc, but if we did, we would point it here |
|
459 |
* I don't think we ever get a handle on the List Proc, but if we did, we would point it here |
459 |
*/ |
|
460 |
*/ |
460 |
PUGL_Combo ugl_combo = (PUGL_Combo)GetWindowLong(hWnd, GWL_USERDATA); |
|
461 |
PUGL_Combo ugl_combo = (PUGL_Combo)GetWindowLong(hWnd, GWL_USERDATA); |
461 |
if (ugl_combo != NULL) return ugl_combo->listProc(hWnd, message, wParam, lParam); |
|
462 |
if (ugl_combo != NULL) return ugl_combo->listProc(hWnd, message, wParam, lParam); |
462 |
return 0; |
|
463 |
return 0; |
463 |
} |
|
464 |
} |
464 |
//======================================================================================== |
|
465 |
//======================================================================================== |
465 |
LRESULT CALLBACK _Combo_Text_Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { |
|
466 |
LRESULT CALLBACK _Combo_Text_Proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { |
466 |
/* |
|
467 |
/* |
467 |
* This is set in _Combo_New() |
|
468 |
* This is set in _Combo_New() |
468 |
* |
|
469 |
* |
469 |
* Because Combos are complex widgets, some messages go to the HWND of the combo, |
|
470 |
* Because Combos are complex widgets, some messages go to the HWND of the combo, |
470 |
* and some go to the HWND of the text component of the combo. |
|
471 |
* and some go to the HWND of the text component of the combo. |
471 |
* This proc handles some of the messages that go to the text component. |
|
472 |
* This proc handles some of the messages that go to the text component. |
472 |
*/ |
|
473 |
*/ |
473 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hWnd, GWL_USERDATA); //this is the parent (the Combo) |
|
474 |
PUGL_Control ugl_control = (PUGL_Control)GetWindowLong(hWnd, GWL_USERDATA); //this is the parent (the Combo) |
474 |
int result = 0; |
|
475 |
int result = 0; |
475 |
switch (message) { |
|
476 |
switch (message) { |
476 |
case WM_KEYDOWN: { |
|
477 |
case WM_KEYDOWN: { |
477 |
if(SendMessage(ugl_control->hWnd, CB_GETDROPPEDSTATE, 0, 0) && wParam == VK_RETURN) { |
|
478 |
if(SendMessage(ugl_control->hWnd, CB_GETDROPPEDSTATE, 0, 0) && wParam == VK_RETURN) { |
478 |
return 0; |
|
479 |
return 0; |
479 |
} |
|
480 |
} |
480 |
result = _Control_ProcessWmKeyDown(ugl_control->hWnd, wParam, lParam); |
|
481 |
result = _Control_ProcessWmKeyDown(ugl_control->hWnd, wParam, lParam); |
481 |
if(wParam == VK_DELETE) { |
|
482 |
if(wParam == VK_DELETE) { |
482 |
_Combo_Text_ProcessWmChar(ugl_control, VK_DELETE); |
|
483 |
_Combo_Text_ProcessWmChar(ugl_control, VK_DELETE); |
483 |
return 0; |
|
484 |
return 0; |
484 |
} |
|
485 |
} |
485 |
} break; |
|
486 |
} break; |
486 |
|
|
487 |
|
487 |
case WM_KEYUP: { |
|
488 |
case WM_KEYUP: { |
488 |
if(SendMessage(ugl_control->hWnd, CB_GETDROPPEDSTATE, 0, 0) && wParam == VK_RETURN) { |
|
489 |
if(SendMessage(ugl_control->hWnd, CB_GETDROPPEDSTATE, 0, 0) && wParam == VK_RETURN) { |
489 |
return 0; |
|
490 |
return 0; |
490 |
} |
|
491 |
} |
491 |
result = _Control_ProcessWmKeyUp(ugl_control->hWnd, wParam, lParam); |
|
492 |
result = _Control_ProcessWmKeyUp(ugl_control->hWnd, wParam, lParam); |
492 |
} break; |
|
493 |
} break; |
493 |
|
|
494 |
|
494 |
case WM_CHAR: { |
|
495 |
case WM_CHAR: { |
495 |
if(wParam != VK_RETURN) { |
|
496 |
if(wParam != VK_RETURN) { |
496 |
result = _Control_ProcessWmChar(ugl_control->hWnd, wParam, lParam); |
|
497 |
result = _Control_ProcessWmChar(ugl_control->hWnd, wParam, lParam); |
497 |
} |
|
498 |
} |
498 |
switch (wParam){ |
|
499 |
switch (wParam){ |
499 |
case VK_TAB: { |
|
500 |
case VK_TAB: { |
500 |
return 0; |
|
501 |
return 0; |
501 |
} break; |
|
502 |
} break; |
502 |
case VK_RETURN: { |
|
503 |
case VK_RETURN: { |
503 |
if(SendMessage(ugl_control->hWnd, CB_GETDROPPEDSTATE, 0, 0)) { |
|
504 |
if(SendMessage(ugl_control->hWnd, CB_GETDROPPEDSTATE, 0, 0)) { |
504 |
_Combo_Text_ProcessWmChar(ugl_control, VK_RETURN); |
|
505 |
_Combo_Text_ProcessWmChar(ugl_control, VK_RETURN); |
505 |
} else { |
|
506 |
} else { |
506 |
MessageBeep(MB_OK); |
|
507 |
MessageBeep(MB_OK); |
507 |
result = _Control_ProcessWmChar(ugl_control->hWnd, wParam, lParam); |
|
508 |
result = _Control_ProcessWmChar(ugl_control->hWnd, wParam, lParam); |
508 |
ComboCallback(ugl_control->widget.callback_target, UGL_EVENT_COMBO_DEFAULTSELECTION); |
|
509 |
ComboCallback(ugl_control->widget.callback_target, UGL_EVENT_COMBO_DEFAULTSELECTION); |
509 |
} |
|
510 |
} |
510 |
return 0; |
|
511 |
return 0; |
511 |
} break; |
|
512 |
} break; |
512 |
case VK_ESCAPE: { |
|
513 |
case VK_ESCAPE: { |
513 |
int style = GetWindowLong(hWnd, GWL_STYLE); |
|
514 |
int style = GetWindowLong(hWnd, GWL_STYLE); |
514 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, FALSE, 0); |
|
515 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, FALSE, 0); |
515 |
if ((style & UGL_STYLE_DROP_DOWN) != 0) { |
|
516 |
if ((style & UGL_STYLE_DROP_DOWN) != 0) { |
516 |
if (SendMessage(hWnd, CB_GETDROPPEDSTATE, wParam, lParam) == 0){ |
|
517 |
if (SendMessage(hWnd, CB_GETDROPPEDSTATE, wParam, lParam) == 0){ |
517 |
return 0; |
|
518 |
return 0; |
518 |
}; |
|
519 |
}; |
519 |
|
|
520 |
|
520 |
} |
|
521 |
} |
521 |
} break; |
|
522 |
} break; |
522 |
default : { |
|
523 |
default : { |
523 |
_Combo_Text_ProcessWmChar(ugl_control, wParam); |
|
524 |
_Combo_Text_ProcessWmChar(ugl_control, wParam); |
524 |
return 0; |
|
525 |
return 0; |
525 |
} break; |
|
526 |
} break; |
526 |
} |
|
527 |
} |
527 |
} break; |
|
528 |
} break; |
528 |
|
|
529 |
|
529 |
case WM_CLEAR: |
|
530 |
case WM_CLEAR: |
530 |
case WM_CUT: { |
|
531 |
case WM_CUT: { |
531 |
if (VerifyHelper_HandleCut(ugl_control, hWnd, ((PUGL_Combo)ugl_control)->textProc, message) == FALSE) return 0; |
|
532 |
if (VerifyHelper_HandleCut(ugl_control, hWnd, ((PUGL_Combo)ugl_control)->textProc, message) == FALSE) return 0; |
532 |
break; |
|
533 |
break; |
533 |
} |
|
534 |
} |
534 |
|
|
535 |
|
535 |
case WM_PASTE: { |
|
536 |
case WM_PASTE: { |
536 |
if (VerifyHelper_HandlePaste(ugl_control, hWnd) == FALSE) return 0; |
|
537 |
if (VerifyHelper_HandlePaste(ugl_control, hWnd) == FALSE) return 0; |
537 |
break; |
|
538 |
break; |
538 |
} |
|
539 |
} |
539 |
|
|
540 |
|
540 |
case WM_SETFOCUS: { |
|
541 |
case WM_SETFOCUS: { |
541 |
/* |
|
542 |
/* |
542 |
* When _Control_ForceFocus() is called on a Combo, the native call to |
|
543 |
* When _Control_ForceFocus() is called on a Combo, the native call to |
543 |
* setFocus() sends a WM_SETFOCUS message to the combo, and it immediately |
|
544 |
* setFocus() sends a WM_SETFOCUS message to the combo, and it immediately |
544 |
* bounces the focus to the text component, which causes a WM_KILLFOCUS message |
|
545 |
* bounces the focus to the text component, which causes a WM_KILLFOCUS message |
545 |
* to be sent to the Combo and a WM_SETFOCUS to go to the text component. |
|
546 |
* to be sent to the Combo and a WM_SETFOCUS to go to the text component. |
546 |
* This results in three focus callbacks reported by the combo in java: |
|
547 |
* This results in three focus callbacks reported by the combo in java: |
547 |
* (focus in, focus out, focus in). |
|
548 |
* (focus in, focus out, focus in). |
548 |
*/ |
|
549 |
*/ |
549 |
HWND lastFocusWind = (HWND)wParam; |
|
550 |
HWND lastFocusWind = (HWND)wParam; |
550 |
UGL_Boolean ignoreFocusEvent = (lastFocusWind == ugl_control->hWnd); |
|
551 |
UGL_Boolean ignoreFocusEvent = (lastFocusWind == ugl_control->hWnd); |
551 |
|
|
552 |
|
552 |
_Combo_Text_RestoreText(ugl_control); |
|
553 |
_Combo_Text_RestoreText(ugl_control); |
553 |
|
|
554 |
|
554 |
if (!ignoreFocusEvent) { |
|
555 |
if (!ignoreFocusEvent) { |
555 |
FocusCallback(UGL_WIDGET(ugl_control)->callback_target, UGL_EVENT_FOCUS_IN); |
|
556 |
FocusCallback(UGL_WIDGET(ugl_control)->callback_target, UGL_EVENT_FOCUS_IN); |
556 |
//only send the event if the combo didn't already do it |
|
557 |
//only send the event if the combo didn't already do it |
557 |
} |
|
558 |
} |
558 |
} break; |
|
559 |
} break; |
559 |
|
|
560 |
|
560 |
case WM_KILLFOCUS: { |
|
561 |
case WM_KILLFOCUS: { |
561 |
HWND lastFocusWind = (HWND)wParam; |
|
562 |
HWND lastFocusWind = (HWND)wParam; |
562 |
UGL_Boolean ignoreFocusEvent = (lastFocusWind == ugl_control->hWnd); |
|
563 |
UGL_Boolean ignoreFocusEvent = (lastFocusWind == ugl_control->hWnd); |
563 |
|
|
564 |
|
564 |
_Combo_Text_SaveText(ugl_control); |
|
565 |
_Combo_Text_SaveText(ugl_control); |
565 |
|
|
566 |
|
566 |
if (!ignoreFocusEvent) { |
|
567 |
if (!ignoreFocusEvent) { |
567 |
FocusCallback(UGL_WIDGET(ugl_control)->callback_target, UGL_EVENT_FOCUS_OUT); |
|
568 |
FocusCallback(UGL_WIDGET(ugl_control)->callback_target, UGL_EVENT_FOCUS_OUT); |
568 |
//only send the event if the combo didn't already do it |
|
569 |
//only send the event if the combo didn't already do it |
569 |
} |
|
570 |
} |
570 |
} break; |
|
571 |
} break; |
571 |
} |
|
572 |
} |
572 |
|
|
573 |
|
573 |
if (result != 0) return result; |
|
574 |
if (result != 0) return result; |
574 |
else return CallWindowProc(((PUGL_Combo)ugl_control)->textProc, hWnd, message, wParam, lParam); |
|
575 |
else return CallWindowProc(((PUGL_Combo)ugl_control)->textProc, hWnd, message, wParam, lParam); |
575 |
} |
|
576 |
} |
576 |
//======================================================================================== |
|
577 |
//======================================================================================== |
577 |
|
|
578 |
|
578 |
LRESULT _Combo_CommandChild(PUGL_Control ugl_control, WPARAM wParam, HWND hWnd){ |
|
579 |
LRESULT _Combo_CommandChild(PUGL_Control ugl_control, WPARAM wParam, HWND hWnd){ |
579 |
UGL_Int handle = (UGL_Int)ugl_control; |
|
580 |
UGL_Int handle = (UGL_Int)ugl_control; |
580 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
|
581 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
581 |
LRESULT result = 1; |
|
582 |
LRESULT result = 1; |
582 |
HWND textHWnd = GetDlgItem(ugl_control->hWnd, CBID_EDIT); |
|
583 |
HWND textHWnd = GetDlgItem(ugl_control->hWnd, CBID_EDIT); |
583 |
HWND listHWnd = GetDlgItem(ugl_control->hWnd, CBID_LIST); |
|
584 |
HWND listHWnd = GetDlgItem(ugl_control->hWnd, CBID_LIST); |
584 |
int code = HIWORD(wParam); |
|
585 |
int code = HIWORD(wParam); |
585 |
int current_control = LOWORD(wParam); |
|
586 |
int current_control = LOWORD(wParam); |
586 |
/* |
|
587 |
/* |
587 |
* This is weird. For starters, we have a really quarky way of sizing Combos. |
|
588 |
* This is weird. For starters, we have a really quarky way of sizing Combos. |
588 |
* We have to return the size of an unexpanded Combo from _Combo_GetMinimumSize() |
|
589 |
* We have to return the size of an unexpanded Combo from _Combo_GetMinimumSize() |
589 |
* so that the Java layouts work correctly. But we have to return the size of an |
|
590 |
* so that the Java layouts work correctly. But we have to return the size of an |
590 |
* expanded Combo from _Control_GetBounds(), otherwise the OS won't give us enough room |
|
591 |
* expanded Combo from _Control_GetBounds(), otherwise the OS won't give us enough room |
591 |
* to show an expanded Combo. We do this by causing Control_SetBounds() to go through the |
|
592 |
* to show an expanded Combo. We do this by causing Control_SetBounds() to go through the |
592 |
* procs and override UI_SET_BOUNDS in _Combo_Proc to take the bounds set in _Combo_GetMinimumSize() |
|
593 |
* procs and override UI_SET_BOUNDS in _Combo_Proc to take the bounds set in _Combo_GetMinimumSize() |
593 |
* and increase the height to account for the expanded Combo. |
|
594 |
* and increase the height to account for the expanded Combo. |
594 |
* That brings us to the next few lines of code. They are necessary because of a Windows bug. It |
|
595 |
* That brings us to the next few lines of code. They are necessary because of a Windows bug. It |
595 |
* seems that no matter what we set the bounds of the window to be in UI_SET_BOUNDS, and eventually |
|
596 |
* seems that no matter what we set the bounds of the window to be in UI_SET_BOUNDS, and eventually |
596 |
* _Control_SetBounds(), Windows always resets the height according to some other constraint. But we |
|
597 |
* _Control_SetBounds(), Windows always resets the height according to some other constraint. But we |
597 |
* have to control this to satisfy the eSWT Get/SetVisibleItemCount() API. So the fix is to resize the |
|
598 |
* have to control this to satisfy the eSWT Get/SetVisibleItemCount() API. So the fix is to resize the |
598 |
* drop-down window after Windows ignores our request, which we do here, right after the user presses |
|
599 |
* drop-down window after Windows ignores our request, which we do here, right after the user presses |
599 |
* the drop-down button. |
|
600 |
* the drop-down button. |
600 |
*/ |
|
601 |
*/ |
601 |
int x, y, width, height = 0; |
|
602 |
int x, y, width, height = 0; |
602 |
RECT boundsRect; |
|
603 |
RECT boundsRect; |
603 |
UGL_Error error = NULL; |
|
604 |
UGL_Error error = NULL; |
604 |
Control_GetBounds((UGL_Int)ugl_control, &x, &y, &width, &height, error); |
|
605 |
Control_GetBounds((UGL_Int)ugl_control, &x, &y, &width, &height, error); |
605 |
boundsRect.left = x; |
|
606 |
boundsRect.left = x; |
606 |
boundsRect.right = x + width; |
|
607 |
boundsRect.right = x + width; |
607 |
boundsRect.top = y; |
|
608 |
boundsRect.top = y; |
608 |
boundsRect.bottom = y + height; |
|
609 |
boundsRect.bottom = y + height; |
609 |
SendMessage(ugl_control->hWnd, UI_SET_BOUNDS, (WPARAM)&boundsRect, (LPARAM)&error); |
|
610 |
SendMessage(ugl_control->hWnd, UI_SET_BOUNDS, (WPARAM)&boundsRect, (LPARAM)&error); |
610 |
|
|
611 |
|
611 |
switch (code) { |
|
612 |
switch (code) { |
612 |
case CBN_SELCHANGE: { |
|
613 |
case CBN_SELCHANGE: { |
613 |
int current_item = SendMessage(hWnd, CB_GETCURSEL, 0, 0); |
|
614 |
int current_item = SendMessage(hWnd, CB_GETCURSEL, 0, 0); |
614 |
|
|
615 |
|
615 |
if (current_item == 0) { |
|
616 |
if (current_item == 0) { |
616 |
int count = SendMessage(hWnd, CB_GETCOUNT, 0, 0); |
|
617 |
int count = SendMessage(hWnd, CB_GETCOUNT, 0, 0); |
617 |
if (count == 0) current_item = -1; |
|
618 |
if (count == 0) current_item = -1; |
618 |
} |
|
619 |
} |
619 |
|
|
620 |
|
620 |
if (current_control != CBID_LIST) { |
|
621 |
if (current_control != CBID_LIST) { |
621 |
/* |
|
622 |
/* |
622 |
* This is necessary because this message comes through twice per item |
|
623 |
* This is necessary because this message comes through twice per item |
623 |
* selection: once for the list and once for something else. |
|
624 |
* selection: once for the list and once for something else. |
624 |
* It doesn't seem that the second one is for the text, because |
|
625 |
* It doesn't seem that the second one is for the text, because |
625 |
* the value of current_control is 0, not CBID_TEXT (1001). |
|
626 |
* the value of current_control is 0, not CBID_TEXT (1001). |
626 |
* Regardless of why the second call comes through, we're only interested |
|
627 |
* Regardless of why the second call comes through, we're only interested |
627 |
* in the one for the list control. |
|
628 |
* in the one for the list control. |
628 |
* Also note that we don't change the result variable, which means that |
|
629 |
* Also note that we don't change the result variable, which means that |
629 |
* processing on this message will end here, but that's OK because the |
|
630 |
* processing on this message will end here, but that's OK because the |
630 |
* processing that occurs for the list control is sufficient. |
|
631 |
* processing that occurs for the list control is sufficient. |
631 |
*/ |
|
632 |
*/ |
632 |
break; |
|
633 |
break; |
633 |
} |
|
634 |
} |
634 |
|
|
635 |
|
635 |
ChoiceCallback(UGL_WIDGET(ugl_combo)->callback_target, current_item); |
|
636 |
ChoiceCallback(UGL_WIDGET(ugl_combo)->callback_target, current_item); |
636 |
//don't mess with result -- if we return 0 we skip important processings |
|
637 |
//don't mess with result -- if we return 0 we skip important processings |
637 |
|
|
638 |
|
638 |
} break; |
|
639 |
} break; |
639 |
|
|
640 |
|
640 |
case CBN_EDITCHANGE: { |
|
641 |
case CBN_EDITCHANGE: { |
641 |
} break; |
|
642 |
} break; |
642 |
|
|
643 |
|
643 |
case CBN_SELENDOK: { |
|
644 |
case CBN_SELENDOK: { |
644 |
//This called whenever the user selects an item from the list |
|
645 |
//This called whenever the user selects an item from the list |
645 |
//(using the mouse or the keyboard) |
|
646 |
//(using the mouse or the keyboard) |
646 |
ComboCallback(UGL_WIDGET(ugl_combo)->callback_target, UGL_EVENT_COMBO_TEXT); |
|
647 |
ComboCallback(UGL_WIDGET(ugl_combo)->callback_target, UGL_EVENT_COMBO_TEXT); |
647 |
} break; |
|
648 |
} break; |
648 |
case CBN_SETFOCUS: { |
|
649 |
case CBN_SETFOCUS: { |
649 |
_Combo_Text_RestoreText(ugl_control); |
|
650 |
_Combo_Text_RestoreText(ugl_control); |
650 |
} break; |
|
651 |
} break; |
651 |
case CBN_KILLFOCUS: { |
|
652 |
case CBN_KILLFOCUS: { |
652 |
_Combo_Text_RestoreText(ugl_control); |
|
653 |
_Combo_Text_RestoreText(ugl_control); |
653 |
} break; |
|
654 |
} break; |
654 |
case CBN_DROPDOWN: { |
|
655 |
case CBN_DROPDOWN: { |
655 |
_Combo_Text_RestoreText(ugl_control); |
|
656 |
_Combo_Text_RestoreText(ugl_control); |
656 |
return 0; |
|
657 |
return 0; |
657 |
} break; |
|
658 |
} break; |
658 |
case CBN_CLOSEUP: { |
|
659 |
case CBN_CLOSEUP: { |
659 |
_Combo_Text_RestoreText(ugl_control); |
|
660 |
_Combo_Text_RestoreText(ugl_control); |
660 |
return 0; |
|
661 |
return 0; |
661 |
} break; |
|
662 |
} break; |
662 |
case CBN_SELENDCANCEL: { |
|
663 |
case CBN_SELENDCANCEL: { |
663 |
if(!UGL_COMBO(ugl_control)->is_read_only && |
|
664 |
if(!UGL_COMBO(ugl_control)->is_read_only && |
664 |
SendMessage(ugl_control->hWnd, CB_GETDROPPEDSTATE, 0, 0)) { |
|
665 |
SendMessage(ugl_control->hWnd, CB_GETDROPPEDSTATE, 0, 0)) { |
665 |
_Combo_Text_SaveText(ugl_control); |
|
666 |
_Combo_Text_SaveText(ugl_control); |
666 |
} |
|
667 |
} |
667 |
} break; |
|
668 |
} break; |
668 |
default:{ |
|
669 |
default:{ |
669 |
|
|
670 |
|
670 |
} break; |
|
671 |
} break; |
671 |
} |
|
672 |
} |
672 |
return result; |
|
673 |
return result; |
673 |
|
|
674 |
|
674 |
} |
|
675 |
} |
675 |
|
|
676 |
|
676 |
//======================================================================================== |
|
677 |
//======================================================================================== |
677 |
|
|
678 |
|
678 |
int _Combo_CTLCOLOR(PUGL_Control parent_control, HDC hdc, PUGL_Control color_control){ |
|
679 |
int _Combo_CTLCOLOR(PUGL_Control parent_control, HDC hdc, PUGL_Control color_control){ |
679 |
/* |
|
680 |
/* |
680 |
* This function gets called whenever a WM_CTLCOLOREDIT or WM_CTLCOLORLISTBOX messsage |
|
681 |
* This function gets called whenever a WM_CTLCOLOREDIT or WM_CTLCOLORLISTBOX messsage |
681 |
* comes through the ComboProc and doesn't map to a UGL_Control. It means that the |
|
682 |
* comes through the ComboProc and doesn't map to a UGL_Control. It means that the |
682 |
* current control is the child text or child list of a combo. That means that we need |
|
683 |
* current control is the child text or child list of a combo. That means that we need |
683 |
* to get the correct background and foreground color information from the parent, where |
|
684 |
* to get the correct background and foreground color information from the parent, where |
684 |
* it gets stored on a Control_SetBackground() or Control_SetForeGround() call. |
|
685 |
* it gets stored on a Control_SetBackground() or Control_SetForeGround() call. |
685 |
*/ |
|
686 |
*/ |
686 |
|
|
687 |
|
687 |
COLORREF foreground; |
|
688 |
COLORREF foreground; |
688 |
COLORREF background; |
|
689 |
COLORREF background; |
689 |
HGDIOBJ background_brush; |
|
690 |
HGDIOBJ background_brush; |
690 |
|
|
691 |
|
691 |
/* |
|
692 |
/* |
692 |
* We don't have any special logic to set the foreground |
|
693 |
* We don't have any special logic to set the foreground |
693 |
* because all the controls use COLOR_WINDOWTEXT. |
|
694 |
* because all the controls use COLOR_WINDOWTEXT. |
694 |
*/ |
|
695 |
*/ |
695 |
foreground = (parent_control->foreground_color != NULL) ? parent_control->foreground_color->color : GetSysColor(COLOR_WINDOWTEXT); |
|
696 |
foreground = (parent_control->foreground_color != NULL) ? parent_control->foreground_color->color : GetSysColor(COLOR_WINDOWTEXT); |
696 |
|
|
697 |
|
697 |
if (parent_control->background_color != NULL) { |
|
698 |
if (parent_control->background_color != NULL) { |
698 |
background_brush = Color_GetBrush(parent_control->background_color); |
|
699 |
background_brush = Color_GetBrush(parent_control->background_color); |
699 |
background = parent_control->background_color->color; |
|
700 |
background = parent_control->background_color->color; |
700 |
} else { |
|
701 |
} else { |
701 |
background_brush = GetSysColorBrush(COLOR_WINDOW); |
|
702 |
background_brush = GetSysColorBrush(COLOR_WINDOW); |
702 |
background = GetSysColor(COLOR_WINDOW); |
|
703 |
background = GetSysColor(COLOR_WINDOW); |
703 |
|
|
704 |
|
704 |
} |
|
705 |
} |
705 |
|
|
706 |
|
706 |
SetTextColor(hdc, foreground); |
|
707 |
SetTextColor(hdc, foreground); |
707 |
SetBkColor(hdc, background); |
|
708 |
SetBkColor(hdc, background); |
708 |
return (int)background_brush; |
|
709 |
return (int)background_brush; |
709 |
} |
|
710 |
} |
710 |
|
|
711 |
|
711 |
//======================================================================================== |
|
712 |
//======================================================================================== |
712 |
|
|
713 |
|
713 |
void _Combo_GetMinimumSize(UGL_Int handle, POINT *point, UGL_Error uglError) { |
|
714 |
void _Combo_GetMinimumSize(UGL_Int handle, POINT *point, UGL_Error uglError) { |
714 |
/* |
|
715 |
/* |
715 |
* This is a rough mimic of how they do things in SWT. |
|
716 |
* This is a rough mimic of how they do things in SWT. |
716 |
* The logic goes something like this: |
|
717 |
* The logic goes something like this: |
717 |
* For width: find the longest item in the combo, draw that string |
|
718 |
* For width: find the longest item in the combo, draw that string |
718 |
* to an HDC using the current font, figure out the width of the rect |
|
719 |
* to an HDC using the current font, figure out the width of the rect |
719 |
* that surrounds the text you just drew, and add the width of the drop- |
|
720 |
* that surrounds the text you just drew, and add the width of the drop- |
720 |
* down button plus a little buffer just so things aren't cramped. |
|
721 |
* down button plus a little buffer just so things aren't cramped. |
721 |
* For height: find the height of the button on the combo, plus a little breathing room. |
|
722 |
* For height: find the height of the button on the combo, plus a little breathing room. |
722 |
* Don't worry about how many items are in the drop-down list. We take care of that in |
|
723 |
* Don't worry about how many items are in the drop-down list. We take care of that in |
723 |
* SetBounds(). If we return that size here, then the layouts will always |
|
724 |
* SetBounds(). If we return that size here, then the layouts will always |
724 |
* treat the Combo like its size is its expanded size. |
|
725 |
* treat the Combo like its size is its expanded size. |
725 |
* The exceptions are that we only show the first six items in the combo |
|
726 |
* The exceptions are that we only show the first six items in the combo |
726 |
* if there are more than 6, and we scale to the width of the second- |
|
727 |
* if there are more than 6, and we scale to the width of the second- |
727 |
* longest item in the combo if the longest item is 15 or more chars longer |
|
728 |
* longest item in the combo if the longest item is 15 or more chars longer |
728 |
* than the second-longest. |
|
729 |
* than the second-longest. |
729 |
* |
|
730 |
* |
730 |
* We probably need to do a bit of error handling on the OS calls. |
|
731 |
* We probably need to do a bit of error handling on the OS calls. |
731 |
* We use a default CBSize of 52, that is hard-coded in SWT. That may |
|
732 |
* We use a default CBSize of 52, that is hard-coded in SWT. That may |
732 |
* cause some problems sooner or later. |
|
733 |
* cause some problems sooner or later. |
733 |
*/ |
|
734 |
*/ |
734 |
|
|
735 |
|
735 |
PUGL_Control ugl_control = UGL_CONTROL(handle); |
|
736 |
PUGL_Control ugl_control = UGL_CONTROL(handle); |
736 |
HWND hWnd = ugl_control->hWnd; |
|
737 |
HWND hWnd = ugl_control->hWnd; |
737 |
int width = 0; |
|
738 |
int width = 0; |
738 |
int height = 0; |
|
739 |
int height = 0; |
739 |
int num_items = SendMessage(hWnd, CB_GETCOUNT, 0, 0); |
|
740 |
int num_items = SendMessage(hWnd, CB_GETCOUNT, 0, 0); |
740 |
int max_length = 0; |
|
741 |
int max_length = 0; |
741 |
int current_length = 0; |
|
742 |
int current_length = 0; |
742 |
int second_longest = 0; |
|
743 |
int second_longest = 0; |
743 |
TEXTMETRIC tm; |
|
744 |
TEXTMETRIC tm; |
744 |
HDC hDC = GetDC(hWnd); |
|
745 |
HDC hDC = GetDC(hWnd); |
745 |
int working_vertical_count = 0; |
|
746 |
int working_vertical_count = 0; |
746 |
int i = 0; |
|
747 |
int i = 0; |
747 |
int max_viewable_items = 6; |
|
748 |
int max_viewable_items = 6; |
748 |
COMBOBOXINFO pcbi; |
|
749 |
COMBOBOXINFO pcbi; |
749 |
int presetCBSize = 52; //from SWT Default |
|
750 |
int presetCBSize = 52; //from SWT Default |
750 |
RECT text_size_rect; |
|
751 |
RECT text_size_rect; |
751 |
HGDIOBJ newFont = 0; |
|
752 |
HGDIOBJ newFont = 0; |
752 |
int flags = DT_CALCRECT | DT_NOPREFIX; |
|
753 |
int flags = DT_CALCRECT | DT_NOPREFIX; |
753 |
int first_index = 0; |
|
754 |
int first_index = 0; |
754 |
int second_index = 0; |
|
755 |
int second_index = 0; |
755 |
int widthBuffer = 10; //based on testing |
|
756 |
int widthBuffer = 10; //based on testing |
756 |
int heightBuffer = 3; |
|
757 |
int heightBuffer = 3; |
757 |
|
|
758 |
|
758 |
|
|
759 |
|
759 |
/* |
|
760 |
/* |
760 |
* Find and record the number of chars and indexes of the longest and second- |
|
761 |
* Find and record the number of chars and indexes of the longest and second- |
761 |
* longest strings in the combo |
|
762 |
* longest strings in the combo |
762 |
*/ |
|
763 |
*/ |
763 |
for (i = 0; i<num_items; i++){ |
|
764 |
for (i = 0; i<num_items; i++){ |
764 |
current_length = SendMessage(hWnd, CB_GETLBTEXTLEN, i, 0); |
|
765 |
current_length = SendMessage(hWnd, CB_GETLBTEXTLEN, i, 0); |
765 |
if (current_length > max_length) { |
|
766 |
if (current_length > max_length) { |
766 |
second_longest = max_length; |
|
767 |
second_longest = max_length; |
767 |
max_length = current_length; |
|
768 |
max_length = current_length; |
768 |
second_index = first_index; |
|
769 |
second_index = first_index; |
769 |
first_index = i; |
|
770 |
first_index = i; |
770 |
} |
|
771 |
} |
771 |
} |
|
772 |
} |
772 |
|
|
773 |
|
773 |
/* |
|
774 |
/* |
774 |
* Now determine whether you want to use the longest or second-longest, and |
|
775 |
* Now determine whether you want to use the longest or second-longest, and |
775 |
* find the width in pixels, based on drawing that string to the screen in the |
|
776 |
* find the width in pixels, based on drawing that string to the screen in the |
776 |
* current font. |
|
777 |
* current font. |
777 |
* No need to bother with all the overhead if we know that the combo is empty. |
|
778 |
* No need to bother with all the overhead if we know that the combo is empty. |
778 |
*/ |
|
779 |
*/ |
779 |
if (num_items != 0) { |
|
780 |
if (num_items != 0) { |
780 |
UGL_String text; |
|
781 |
UGL_String text; |
781 |
int working_horizontal_count = 0; |
|
782 |
int working_horizontal_count = 0; |
782 |
|
|
783 |
|
783 |
if (second_longest != 0 && (max_length - second_longest) > 15) { |
|
784 |
if (second_longest != 0 && (max_length - second_longest) > 15) { |
784 |
working_horizontal_count = second_longest; |
|
785 |
working_horizontal_count = second_longest; |
785 |
text = (UGL_String)calloc(sizeof(TCHAR), working_horizontal_count+1); |
|
786 |
text = (UGL_String)calloc(sizeof(TCHAR), working_horizontal_count+1); |
786 |
SendMessage(hWnd, CB_GETLBTEXT, second_index, (LPARAM)text); |
|
787 |
SendMessage(hWnd, CB_GETLBTEXT, second_index, (LPARAM)text); |
787 |
/*SendMessage(hWnd, CB_SETDROPPEDWIDTH, tm.tmAveCharWidth * max_length * 0.80, 0);*/ |
|
788 |
/*SendMessage(hWnd, CB_SETDROPPEDWIDTH, tm.tmAveCharWidth * max_length * 0.80, 0);*/ |
788 |
} |
|
789 |
} |
789 |
else { |
|
790 |
else { |
790 |
working_horizontal_count = max_length; |
|
791 |
working_horizontal_count = max_length; |
791 |
text = (UGL_String)calloc(sizeof(TCHAR), working_horizontal_count+1); |
|
792 |
text = (UGL_String)calloc(sizeof(TCHAR), working_horizontal_count+1); |
792 |
SendMessage(hWnd, CB_GETLBTEXT, first_index, (LPARAM)text); |
|
793 |
SendMessage(hWnd, CB_GETLBTEXT, first_index, (LPARAM)text); |
793 |
} |
|
794 |
} |
794 |
|
|
795 |
|
795 |
newFont = (HGDIOBJ)SendMessage(hWnd, WM_GETFONT, 0, 0); |
|
796 |
newFont = (HGDIOBJ)SendMessage(hWnd, WM_GETFONT, 0, 0); |
796 |
SelectObject(hDC, newFont); |
|
797 |
SelectObject(hDC, newFont); |
797 |
DrawText(hDC, text, working_horizontal_count, (LPRECT)&text_size_rect, flags); |
|
798 |
DrawText(hDC, text, working_horizontal_count, (LPRECT)&text_size_rect, flags); |
798 |
width = text_size_rect.right - text_size_rect.left; |
|
799 |
width = text_size_rect.right - text_size_rect.left; |
799 |
width += widthBuffer; //Just so everything isn't really cramped |
|
800 |
width += widthBuffer; //Just so everything isn't really cramped |
800 |
free(text); |
|
801 |
free(text); |
801 |
} |
|
802 |
} |
802 |
else { |
|
803 |
else { |
803 |
/* |
|
804 |
/* |
804 |
* Since the combo is empty, make it the size of a six-character string |
|
805 |
* Since the combo is empty, make it the size of a six-character string |
805 |
* in the default font. |
|
806 |
* in the default font. |
806 |
*/ |
|
807 |
*/ |
807 |
GetTextMetrics(hDC, (LPTEXTMETRIC)&tm); |
|
808 |
GetTextMetrics(hDC, (LPTEXTMETRIC)&tm); |
808 |
width = tm.tmAveCharWidth * 6; |
|
809 |
width = tm.tmAveCharWidth * 6; |
809 |
} |
|
810 |
} |
810 |
|
|
811 |
|
811 |
pcbi.cbSize = presetCBSize; |
|
812 |
pcbi.cbSize = presetCBSize; |
812 |
|
|
813 |
|
813 |
/** |
|
814 |
/** |
814 |
* WinCE does not have the GetComboBoxInfo method so the message has to be |
|
815 |
* WinCE does not have the GetComboBoxInfo method so the message has to be |
815 |
* used directly instead. |
|
816 |
* used directly instead. |
816 |
*/ |
|
817 |
*/ |
817 |
#ifdef _WIN32_WCE |
|
818 |
#ifdef _WIN32_WCE |
818 |
if (SendMessage(hWnd, CB_GETCOMBOBOXINFO, (WPARAM)0, (LPARAM)&pcbi)) { |
|
819 |
if (SendMessage(hWnd, CB_GETCOMBOBOXINFO, (WPARAM)0, (LPARAM)&pcbi)) { |
819 |
#else |
|
820 |
#else |
820 |
if (GetComboBoxInfo(hWnd, &pcbi)) { |
|
821 |
if (GetComboBoxInfo(hWnd, &pcbi)) { |
821 |
#endif |
|
822 |
#endif |
822 |
width += pcbi.rcItem.left + (pcbi.rcButton.right - pcbi.rcButton.left); |
|
823 |
width += pcbi.rcItem.left + (pcbi.rcButton.right - pcbi.rcButton.left); |
823 |
height = pcbi.rcButton.bottom - pcbi.rcButton.top; |
|
824 |
height = pcbi.rcButton.bottom - pcbi.rcButton.top; |
824 |
height += heightBuffer; |
|
825 |
height += heightBuffer; |
825 |
} |
|
826 |
} |
826 |
else { |
|
827 |
else { |
827 |
/* |
|
828 |
/* |
828 |
* If the call fails, which it shouldn't, just return the default values |
|
829 |
* If the call fails, which it shouldn't, just return the default values |
829 |
* that _Control_GetMinimumSize returns. |
|
830 |
* that _Control_GetMinimumSize returns. |
830 |
*/ |
|
831 |
*/ |
831 |
width = 64; |
|
832 |
width = 64; |
832 |
height = 64; |
|
833 |
height = 64; |
833 |
} |
|
834 |
} |
834 |
|
|
835 |
|
835 |
ReleaseDC (hWnd, hDC); |
|
836 |
ReleaseDC (hWnd, hDC); |
836 |
|
|
837 |
|
837 |
point->x = width; |
|
838 |
point->x = width; |
838 |
point->y = height; |
|
839 |
point->y = height; |
839 |
|
|
840 |
|
840 |
} |
|
841 |
} |
841 |
|
|
842 |
|
842 |
//======================================================================================== |
|
843 |
//======================================================================================== |
843 |
|
|
844 |
|
844 |
void _Dispose_Combo(UGL_Int handle, UGL_Error uglError){ |
|
845 |
void _Dispose_Combo(UGL_Int handle, UGL_Error uglError){ |
845 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
|
846 |
PUGL_Combo ugl_combo = UGL_COMBO(handle); |
846 |
if(ugl_combo->text != NULL) |
|
847 |
if(ugl_combo->text != NULL) |
847 |
free(ugl_combo->text); |
|
848 |
free(ugl_combo->text); |
848 |
if(comboHwnd != NULL) |
+- |
|
|
849 |
free(comboHwnd); |
|
|
|
850 |
_Dispose_Scrollable(handle, uglError); |
= |
849 |
_Dispose_Scrollable(handle, uglError); |
851 |
} |
|
850 |
} |
852 |
|
|
851 |
|
853 |
UGL_Boolean _Combo_Text_ProcessWmChar(PUGL_Control ugl_control, TCHAR ch) { |
|
852 |
UGL_Boolean _Combo_Text_ProcessWmChar(PUGL_Control ugl_control, TCHAR ch) { |
854 |
TCHAR *curStr=NULL, *newStr=NULL; |
|
853 |
TCHAR *curStr=NULL, *newStr=NULL; |
855 |
UGL_Boolean modify = FALSE; |
|
854 |
UGL_Boolean modify = FALSE; |
856 |
DWORD rs; |
|
855 |
DWORD rs; |
857 |
int start, end, len; |
|
856 |
int start, end, len; |
858 |
|
|
857 |
|
859 |
rs = (DWORD)SendMessage(ugl_control->hWnd, CB_GETEDITSEL, 0, 0); |
|
858 |
rs = (DWORD)SendMessage(ugl_control->hWnd, CB_GETEDITSEL, 0, 0); |
860 |
start = LOWORD(rs); |
|
859 |
start = LOWORD(rs); |
861 |
end = HIWORD(rs); |
|
860 |
end = HIWORD(rs); |
862 |
|
|
861 |
|
863 |
len = GetWindowTextLength(ugl_control->hWnd); |
|
862 |
len = GetWindowTextLength(ugl_control->hWnd); |
864 |
curStr = (TCHAR *)calloc(len + 1, sizeof(TCHAR)); |
|
863 |
curStr = (TCHAR *)calloc(len + 1, sizeof(TCHAR)); |
865 |
if(curStr == NULL) |
|
864 |
if(curStr == NULL) |
866 |
return FALSE; |
|
865 |
return FALSE; |
867 |
newStr = (TCHAR *)calloc(len + 2, sizeof(TCHAR)); |
|
866 |
newStr = (TCHAR *)calloc(len + 2, sizeof(TCHAR)); |
868 |
if(newStr == NULL) { |
|
867 |
if(newStr == NULL) { |
869 |
free(curStr); |
|
868 |
free(curStr); |
870 |
return FALSE; |
|
869 |
return FALSE; |
871 |
} |
|
870 |
} |
872 |
|
|
871 |
|
873 |
GetWindowText(ugl_control->hWnd, (LPTSTR)curStr, len + 1); |
|
872 |
GetWindowText(ugl_control->hWnd, (LPTSTR)curStr, len + 1); |
874 |
switch(ch) { |
|
873 |
switch(ch) { |
875 |
case VK_RETURN: { |
|
874 |
case VK_RETURN: { |
876 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, FALSE, 0); |
|
875 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, FALSE, 0); |
877 |
SetWindowText(ugl_control->hWnd, (LPTSTR)curStr); |
|
876 |
SetWindowText(ugl_control->hWnd, (LPTSTR)curStr); |
878 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(len, len)); |
|
877 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(len, len)); |
879 |
} break; |
|
878 |
} break; |
880 |
case VK_DELETE : { |
|
879 |
case VK_DELETE : { |
881 |
if(len == start) { |
|
880 |
if(len == start) { |
882 |
break; |
|
881 |
break; |
883 |
} |
|
882 |
} |
884 |
|
|
883 |
|
885 |
modify = TRUE; |
|
884 |
modify = TRUE; |
886 |
if(start == end) { |
|
885 |
if(start == end) { |
887 |
_Combo_Text_CombineNewString(curStr, newStr, start, end+1, 0); |
|
886 |
_Combo_Text_CombineNewString(curStr, newStr, start, end+1, 0); |
888 |
} else { |
|
887 |
} else { |
889 |
_Combo_Text_CombineNewString(curStr, newStr, start, end, 0); |
|
888 |
_Combo_Text_CombineNewString(curStr, newStr, start, end, 0); |
890 |
} |
|
889 |
} |
891 |
len = _tcslen(newStr); |
|
890 |
len = _tcslen(newStr); |
892 |
if(len == 0) { |
|
891 |
if(len == 0) { |
893 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
|
892 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
894 |
break; |
|
893 |
break; |
895 |
} |
|
894 |
} |
896 |
|
|
895 |
|
897 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, TRUE, 0); |
|
896 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, TRUE, 0); |
898 |
_Combo_Text_FindAndSelectItem(ugl_control->hWnd, (LPCSTR)newStr); |
|
897 |
_Combo_Text_FindAndSelectItem(ugl_control->hWnd, (LPCSTR)newStr); |
899 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
|
898 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
900 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start, start)); |
|
899 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start, start)); |
901 |
} break; |
|
900 |
} break; |
902 |
case VK_BACK : { |
|
901 |
case VK_BACK : { |
903 |
if(end == 0) { |
|
902 |
if(end == 0) { |
904 |
break; |
|
903 |
break; |
905 |
} |
|
904 |
} |
906 |
|
|
905 |
|
907 |
modify = TRUE; |
|
906 |
modify = TRUE; |
908 |
if(start == end) { |
|
907 |
if(start == end) { |
909 |
_Combo_Text_CombineNewString(curStr, newStr, start-1, end, 0); |
|
908 |
_Combo_Text_CombineNewString(curStr, newStr, start-1, end, 0); |
910 |
} else { |
|
909 |
} else { |
911 |
_Combo_Text_CombineNewString(curStr, newStr, start, end, 0); |
|
910 |
_Combo_Text_CombineNewString(curStr, newStr, start, end, 0); |
912 |
} |
|
911 |
} |
913 |
len = _tcslen(newStr); |
|
912 |
len = _tcslen(newStr); |
914 |
if(len == 0) { |
|
913 |
if(len == 0) { |
915 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
|
914 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
916 |
break; |
|
915 |
break; |
917 |
} |
|
916 |
} |
918 |
|
|
917 |
|
919 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, TRUE, 0); |
|
918 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, TRUE, 0); |
920 |
_Combo_Text_FindAndSelectItem(ugl_control->hWnd, (LPCSTR)newStr); |
|
919 |
_Combo_Text_FindAndSelectItem(ugl_control->hWnd, (LPCSTR)newStr); |
921 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
|
920 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
922 |
|
|
921 |
|
923 |
if(start == end) { |
|
922 |
if(start == end) { |
924 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start-1, start-1)); |
|
923 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start-1, start-1)); |
925 |
} else { |
|
924 |
} else { |
926 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start, start)); |
|
925 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start, start)); |
927 |
} |
|
926 |
} |
928 |
} break; |
|
927 |
} break; |
929 |
default : { |
|
928 |
default : { |
930 |
if(_istcntrl(ch)) { |
|
929 |
if(_istcntrl(ch)) { |
931 |
break; |
|
930 |
break; |
932 |
} |
|
931 |
} |
933 |
|
|
932 |
|
934 |
modify = TRUE; |
|
933 |
modify = TRUE; |
935 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, TRUE, 0); |
|
934 |
SendMessage(ugl_control->hWnd, CB_SHOWDROPDOWN, TRUE, 0); |
936 |
_Combo_Text_CombineNewString(curStr, newStr, start, end, ch); |
|
935 |
_Combo_Text_CombineNewString(curStr, newStr, start, end, ch); |
937 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
|
936 |
SetWindowText(ugl_control->hWnd, (LPTSTR)newStr); |
938 |
if(_Combo_Text_FindAndSelectItem(ugl_control->hWnd, (LPCSTR)newStr)) { |
|
937 |
if(_Combo_Text_FindAndSelectItem(ugl_control->hWnd, (LPCSTR)newStr)) { |
939 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start+1, -1)); |
|
938 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start+1, -1)); |
940 |
} else { |
|
939 |
} else { |
941 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start+1, start+1)); |
|
940 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(start+1, start+1)); |
942 |
} |
|
941 |
} |
943 |
} break; |
|
942 |
} break; |
944 |
} |
|
943 |
} |
945 |
|
|
944 |
|
946 |
free(curStr); |
|
945 |
free(curStr); |
947 |
free(newStr); |
|
946 |
free(newStr); |
948 |
|
|
947 |
|
949 |
if(modify) { |
|
948 |
if(modify) { |
950 |
ComboCallback(UGL_WIDGET(ugl_control)->callback_target, UGL_EVENT_COMBO_TEXT); |
|
949 |
ComboCallback(UGL_WIDGET(ugl_control)->callback_target, UGL_EVENT_COMBO_TEXT); |
951 |
} |
|
950 |
} |
952 |
|
|
951 |
|
953 |
return modify; |
|
952 |
return modify; |
954 |
} |
|
953 |
} |
955 |
|
|
954 |
|
956 |
void _Combo_Text_CombineNewString(TCHAR *curStr, TCHAR *newStr, int pos1, int pos2, TCHAR ch) { |
|
955 |
void _Combo_Text_CombineNewString(TCHAR *curStr, TCHAR *newStr, int pos1, int pos2, TCHAR ch) { |
957 |
int off = 0; |
|
956 |
int off = 0; |
958 |
int len = _tcslen(curStr); |
|
957 |
int len = _tcslen(curStr); |
959 |
|
|
958 |
|
960 |
_tcsncpy(newStr, curStr, pos1); |
|
959 |
_tcsncpy(newStr, curStr, pos1); |
961 |
off = pos1; |
|
960 |
off = pos1; |
962 |
if(ch != 0) { |
|
961 |
if(ch != 0) { |
963 |
newStr[off++] = ch; |
|
962 |
newStr[off++] = ch; |
964 |
} |
|
963 |
} |
965 |
_tcsncpy(newStr+off, curStr+pos2, len-pos2); |
|
964 |
_tcsncpy(newStr+off, curStr+pos2, len-pos2); |
966 |
off += len-pos2; |
|
965 |
off += len-pos2; |
967 |
newStr[off] = 0; |
|
966 |
newStr[off] = 0; |
968 |
} |
|
967 |
} |
969 |
|
|
968 |
|
970 |
UGL_Boolean _Combo_Text_FindAndSelectItem(HWND hwnd, LPCSTR str) { |
|
969 |
UGL_Boolean _Combo_Text_FindAndSelectItem(HWND hwnd, LPCSTR str) { |
971 |
return FALSE; |
|
970 |
return FALSE; |
972 |
/* |
|
971 |
/* |
973 |
int index; |
|
972 |
int index; |
974 |
|
|
973 |
|
975 |
index = SendMessage(hwnd, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)str); |
|
974 |
index = SendMessage(hwnd, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)str); |
976 |
if(index == CB_ERR) { |
|
975 |
if(index == CB_ERR) { |
977 |
index = SendMessage(hwnd, CB_FINDSTRING, (WPARAM)-1, (LPARAM)str); |
|
976 |
index = SendMessage(hwnd, CB_FINDSTRING, (WPARAM)-1, (LPARAM)str); |
978 |
} |
|
977 |
} |
979 |
|
|
978 |
|
980 |
if(index != CB_ERR) { |
|
979 |
if(index != CB_ERR) { |
981 |
SendMessage(hwnd, CB_SETCURSEL, (WPARAM)index, (LPARAM)0); |
|
980 |
SendMessage(hwnd, CB_SETCURSEL, (WPARAM)index, (LPARAM)0); |
982 |
} |
|
981 |
} |
983 |
|
|
982 |
|
984 |
return (index != CB_ERR); |
|
983 |
return (index != CB_ERR); |
985 |
*/ |
|
984 |
*/ |
986 |
} |
|
985 |
} |
987 |
|
|
986 |
|
988 |
void _Combo_Text_SaveText(PUGL_Control ugl_control) { |
|
987 |
void _Combo_Text_SaveText(PUGL_Control ugl_control) { |
989 |
DWORD rs; |
|
988 |
DWORD rs; |
990 |
int len; |
|
989 |
int len; |
991 |
if(UGL_COMBO(ugl_control)->is_read_only) { |
|
990 |
if(UGL_COMBO(ugl_control)->is_read_only) { |
992 |
return; |
|
991 |
return; |
993 |
} |
|
992 |
} |
994 |
|
|
993 |
|
995 |
len = GetWindowTextLength(ugl_control->hWnd); |
|
994 |
len = GetWindowTextLength(ugl_control->hWnd); |
996 |
|
|
995 |
|
997 |
if(UGL_COMBO(ugl_control)->text != NULL) |
|
996 |
if(UGL_COMBO(ugl_control)->text != NULL) |
998 |
free(UGL_COMBO(ugl_control)->text); |
|
997 |
free(UGL_COMBO(ugl_control)->text); |
999 |
|
|
998 |
|
1000 |
UGL_COMBO(ugl_control)->text = (TCHAR *)calloc(len + 1, sizeof(TCHAR)); |
|
999 |
UGL_COMBO(ugl_control)->text = (TCHAR *)calloc(len + 1, sizeof(TCHAR)); |
1001 |
if(UGL_COMBO(ugl_control)->text == NULL) { |
|
1000 |
if(UGL_COMBO(ugl_control)->text == NULL) { |
1002 |
return; |
|
1001 |
return; |
1003 |
} |
|
1002 |
} |
1004 |
GetWindowText(ugl_control->hWnd, (LPTSTR)(UGL_COMBO(ugl_control)->text), len + 1); |
|
1003 |
GetWindowText(ugl_control->hWnd, (LPTSTR)(UGL_COMBO(ugl_control)->text), len + 1); |
1005 |
|
|
1004 |
|
1006 |
rs = (DWORD)SendMessage(ugl_control->hWnd, CB_GETEDITSEL, 0, 0); |
|
1005 |
rs = (DWORD)SendMessage(ugl_control->hWnd, CB_GETEDITSEL, 0, 0); |
1007 |
UGL_COMBO(ugl_control)->selStart = LOWORD(rs); |
|
1006 |
UGL_COMBO(ugl_control)->selStart = LOWORD(rs); |
1008 |
UGL_COMBO(ugl_control)->selEnd = HIWORD(rs); |
|
1007 |
UGL_COMBO(ugl_control)->selEnd = HIWORD(rs); |
1009 |
} |
|
1008 |
} |
1010 |
void _Combo_Text_RestoreText(PUGL_Control ugl_control) { |
|
1009 |
void _Combo_Text_RestoreText(PUGL_Control ugl_control) { |
1011 |
if(UGL_COMBO(ugl_control)->is_read_only) { |
|
1010 |
if(UGL_COMBO(ugl_control)->is_read_only) { |
1012 |
return; |
|
1011 |
return; |
1013 |
} |
|
1012 |
} |
1014 |
|
|
1013 |
|
1015 |
if(UGL_COMBO(ugl_control)->text != NULL) { |
|
1014 |
if(UGL_COMBO(ugl_control)->text != NULL) { |
1016 |
SetWindowText(ugl_control->hWnd, (LPTSTR)(UGL_COMBO(ugl_control)->text)); |
|
1015 |
SetWindowText(ugl_control->hWnd, (LPTSTR)(UGL_COMBO(ugl_control)->text)); |
1017 |
|
|
1016 |
|
1018 |
#if !defined(WIN32_PLATFORM_WFSP) |
|
1017 |
#if !defined(WIN32_PLATFORM_WFSP) |
1019 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(UGL_COMBO(ugl_control)->selStart, UGL_COMBO(ugl_control)->selEnd)); |
|
1018 |
SendMessage(ugl_control->hWnd, CB_SETEDITSEL, (WPARAM)0, (LPARAM)MAKELPARAM(UGL_COMBO(ugl_control)->selStart, UGL_COMBO(ugl_control)->selEnd)); |
1020 |
#endif |
|
1019 |
#endif |
1021 |
} |
|
1020 |
} |
1022 |
} |
|
1021 |
} |