]> git.saurik.com Git - wxWidgets.git/blame - src/os2/combobox.cpp
capture mouse to be notified when it exists the popup rect (bug 1372228)
[wxWidgets.git] / src / os2 / combobox.cpp
CommitLineData
0e320a79 1/////////////////////////////////////////////////////////////////////////////
7520f3da 2// Name: src/os2/combobox.cpp
0e320a79 3// Purpose: wxComboBox class
37f214d5 4// Author: David Webster
0e320a79 5// Modified by:
37f214d5 6// Created: 10/13/99
0e320a79 7// RCS-ID: $Id$
37f214d5 8// Copyright: (c) David Webster
65571936 9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
37f214d5
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
7520f3da
WS
15#if wxUSE_COMBOBOX
16
a5bbd1cc
WS
17#include "wx/combobox.h"
18
37f214d5 19#ifndef WX_PRECOMP
a4a16252 20 #include "wx/settings.h"
0e320a79
DW
21#endif
22
37f214d5
DW
23#include "wx/clipbrd.h"
24#include "wx/os2/private.h"
0e320a79 25
0cf6acbf
DW
26#define OWNER_DRAWN_LISTBOX_EXTRA_SPACE (1)
27
28MRESULT EXPENTRY wxComboEditWndProc( HWND hWnd
29 ,UINT uMessage
30 ,MPARAM wParam
31 ,MPARAM lParam
32 );
33//
34// The pointer to standard wnd proc
35//
36static WXFARPROC gfnWndprocEdit = (WXFARPROC)NULL;
37
0e320a79 38IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl)
0e320a79 39
a5bbd1cc 40bool wxComboBox::OS2Command( WXUINT uParam, WXWORD WXUNUSED(wId) )
0e320a79 41{
331f1e07 42 long lSel = GetSelection();
a5bbd1cc 43 wxString sValue;
0e320a79 44
0cf6acbf
DW
45 switch (uParam)
46 {
1de4baa3 47 case CBN_LBSELECT:
331f1e07 48 if (lSel > -1)
0cf6acbf 49 {
a5bbd1cc 50 wxCommandEvent vEvent( wxEVT_COMMAND_COMBOBOX_SELECTED, GetId() );
0cf6acbf 51
331f1e07 52 vEvent.SetInt(lSel);
0cf6acbf 53 vEvent.SetEventObject(this);
0fba44b4 54 vEvent.SetString(GetStringSelection());
a5bbd1cc 55
0cf6acbf
DW
56 ProcessCommand(vEvent);
57 }
58 break;
59
1de4baa3 60 case CBN_EFCHANGE:
0cf6acbf 61 {
a5bbd1cc 62 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED, GetId() );
0cf6acbf
DW
63
64 if (lSel == -1L)
65 sValue = GetValue();
66 else
331f1e07
SN
67 sValue = GetStringSelection();
68 vEvent.SetString(sValue);
0cf6acbf
DW
69 vEvent.SetEventObject(this);
70 ProcessCommand(vEvent);
71 }
72 break;
73 }
74 //
75 // There is no return value for the CBN_ notifications, so always return
7d8268a1 76 // false from here to pass the message to DefWindowProc()
0cf6acbf 77 //
7d8268a1 78 return false;
0cf6acbf
DW
79} // end of wxComboBox::OS2Command
80
584ad2a3
MB
81bool wxComboBox::Create(
82 wxWindow* pParent
83, wxWindowID vId
84, const wxString& rsValue
85, const wxPoint& rPos
86, const wxSize& rSize
87, const wxArrayString& asChoices
88, long lStyle
89, const wxValidator& rValidator
90, const wxString& rsName
91)
92{
93 wxCArrayString chs(asChoices);
94
95 return Create(pParent, vId, rsValue, rPos, rSize, chs.GetCount(),
96 chs.GetStrings(), lStyle, rValidator, rsName);
97}
98
0cf6acbf
DW
99bool wxComboBox::Create(
100 wxWindow* pParent
101, wxWindowID vId
102, const wxString& rsValue
103, const wxPoint& rPos
104, const wxSize& rSize
105, int n
106, const wxString asChoices[]
107, long lStyle
0cf6acbf 108, const wxValidator& rValidator
0cf6acbf
DW
109, const wxString& rsName
110)
0e320a79 111{
7d8268a1 112 m_isShown = false;
0cf6acbf 113
b9b1d6c8 114 if (!CreateControl( pParent
0cf6acbf
DW
115 ,vId
116 ,rPos
117 ,rSize
118 ,lStyle
0cf6acbf 119 ,rValidator
0cf6acbf
DW
120 ,rsName
121 ))
7d8268a1 122 return false;
0cf6acbf
DW
123
124 //
125 // Get the right style
126 //
127 long lSstyle = 0L;
128
129 lSstyle = WS_TABSTOP |
130 WS_VISIBLE;
131
2fbb8fbb
SN
132 // clipping siblings does not yet work
133 // if (lStyle & wxCLIP_SIBLINGS )
134 // lSstyle |= WS_CLIPSIBLINGS;
0cf6acbf
DW
135 if (lStyle & wxCB_READONLY)
136 lSstyle |= CBS_DROPDOWNLIST;
137 else if (lStyle & wxCB_SIMPLE)
138 lSstyle |= CBS_SIMPLE; // A list (shown always) and edit control
139 else
140 lSstyle |= CBS_DROPDOWN;
141
142
0fba44b4 143 if (!OS2CreateControl( _T("COMBOBOX")
0cf6acbf
DW
144 ,lSstyle
145 ))
7d8268a1 146 return false;
0cf6acbf
DW
147
148 //
149 // A choice/combobox normally has a white background (or other, depending
150 // on global settings) rather than inheriting the parent's background colour.
151 //
a756f210 152 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
0cf6acbf 153
154daa94 154 for (int i = 0; i < n; i++)
0cf6acbf
DW
155 {
156 Append(asChoices[i]);
157 }
158
159 SetSize( rPos.x
160 ,rPos.y
161 ,rSize.x
162 ,rSize.y
163 );
331f1e07
SN
164
165 // Set height to use with sizers i.e. without the dropdown listbox
166 wxFont vFont = GetFont();
2fbb8fbb
SN
167 int nEditHeight;
168 wxGetCharSize( GetHWND(), NULL, &nEditHeight, &vFont );
169 nEditHeight = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nEditHeight);
823189ee 170 SetInitialSize(wxSize(-1,nEditHeight+4)); // +2x2 for the border
331f1e07 171
7d8268a1 172 if (!rsValue.empty())
0cf6acbf
DW
173 {
174 SetValue(rsValue);
175 }
176 gfnWndprocEdit = (WXFARPROC)::WinSubclassWindow( (HWND)GetHwnd()
177 ,(PFNWP)wxComboEditWndProc
178 );
5d44b24e 179 ::WinSetWindowULong(GetHwnd(), QWL_USER, (ULONG)this);
7d8268a1
WS
180 Show(true);
181 return true;
0cf6acbf
DW
182} // end of wxComboBox::Create
183
331f1e07
SN
184wxString wxComboBox::GetValue() const
185{
186 return wxGetWindowText(GetHwnd());
187}
188
0cf6acbf
DW
189void wxComboBox::SetValue(
190 const wxString& rsValue
191)
0e320a79 192{
2b5f62a0
VZ
193 if ( HasFlag(wxCB_READONLY) )
194 SetStringSelection(rsValue);
0cf6acbf 195 else
0fba44b4 196 ::WinSetWindowText(GetHwnd(), (PSZ)rsValue.c_str());
0cf6acbf 197} // end of wxComboBox::SetValue
0e320a79 198
0cf6acbf 199//
0e320a79 200// Clipboard operations
0cf6acbf 201//
0e320a79
DW
202void wxComboBox::Copy()
203{
0cf6acbf
DW
204 HWND hWnd = GetHwnd();
205
206 ::WinSendMsg(hWnd, EM_COPY, (MPARAM)0, (MPARAM)0);
207} // end of wxComboBox::Copy
0e320a79
DW
208
209void wxComboBox::Cut()
210{
0cf6acbf
DW
211 HWND hWnd = GetHwnd();
212
213 ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0);
214} // end of wxComboBox::Cut
0e320a79
DW
215
216void wxComboBox::Paste()
217{
0cf6acbf 218 HWND hWnd = GetHwnd();
0e320a79 219
0cf6acbf
DW
220 ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0);
221} // end of wxComboBox::Paste
222
223void wxComboBox::SetEditable(
224 bool bEditable
225)
0e320a79 226{
0cf6acbf
DW
227 HWND hWnd = GetHwnd();
228
229 ::WinSendMsg(hWnd, EM_SETREADONLY, (MPARAM)!bEditable, (MPARAM)0L);
230} // end of wxComboBox::SetEditable
0e320a79 231
0cf6acbf
DW
232void wxComboBox::SetInsertionPoint(
233 long lPos
234)
0e320a79 235{
0cf6acbf
DW
236 HWND hWnd = GetHwnd();
237
238 ::WinSendMsg(hWnd, EM_SETFIRSTCHAR, MPFROMLONG(lPos), (MPARAM)0);
239} // end of wxComboBox::SetInsertionPoint
0e320a79
DW
240
241void wxComboBox::SetInsertionPointEnd()
242{
7d8268a1 243 wxTextPos lPos = GetLastPosition();
0cf6acbf
DW
244
245 SetInsertionPoint(lPos);
246} // end of wxComboBox::SetInsertionPointEnd
0e320a79
DW
247
248long wxComboBox::GetInsertionPoint() const
249{
0cf6acbf
DW
250 long lPos = LONGFROMMR(::WinSendMsg( GetHwnd()
251 ,LM_QUERYSELECTION
252 ,(MPARAM)0
253 ,(MPARAM)0
254 ));
255 if (lPos == LIT_NONE)
256 return wxNOT_FOUND;
257 return lPos;
258} // end of wxComboBox::GetInsertionPoint
0e320a79 259
7d8268a1 260wxTextPos wxComboBox::GetLastPosition() const
0e320a79 261{
0cf6acbf
DW
262 long lLineLength = 0L;
263 WNDPARAMS vParams;
0e320a79 264
0cf6acbf
DW
265 //
266 // Get number of characters in the last (only) line. We'll add this to the character
37f214d5 267 // index for the last line, 1st position.
0cf6acbf 268 //
0e320a79 269
0e320a79 270
0cf6acbf
DW
271 vParams.fsStatus = WPM_CCHTEXT;
272 if (::WinSendMsg( GetHwnd()
273 ,WM_QUERYWINDOWPARAMS
274 ,&vParams
275 ,0
276 ))
277 {
278 lLineLength = (long)vParams.cchText;
279 }
280 else
281 lLineLength = 0L;
282 return lLineLength;
283} // end of wxComboBox::GetLastPosition
284
6670f564
WS
285void wxComboBox::Replace( long lFrom,
286 long lTo,
287 const wxString& rsValue )
0e320a79 288{
37f214d5 289#if wxUSE_CLIPBOARD
0cf6acbf 290 HWND hWnd = GetHwnd();
0e320a79 291
0cf6acbf 292 //
37f214d5 293 // Set selection and remove it
0cf6acbf
DW
294 //
295 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
296 ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0);
0e320a79 297
0cf6acbf 298 //
37f214d5 299 // Now replace with 'value', by pasting.
0cf6acbf
DW
300 //
301 wxSetClipboardData( wxDF_TEXT
302 ,(wxObject *)rsValue.c_str()
303 ,0
304 ,0
305 );
306
307 //
37f214d5 308 // Paste into edit control
0cf6acbf
DW
309 //
310 ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0L);
6670f564
WS
311#else
312 wxUnusedVar(lFrom);
313 wxUnusedVar(lTo);
314 wxUnusedVar(rsValue);
37f214d5 315#endif
0cf6acbf 316} // end of wxComboBox::Replace
0e320a79 317
6670f564 318void wxComboBox::Remove( long lFrom, long lTo)
0e320a79 319{
0cf6acbf
DW
320#if wxUSE_CLIPBOARD
321 HWND hWnd = GetHwnd();
0e320a79 322
0cf6acbf
DW
323 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0);
324 ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0);
6670f564
WS
325#else
326 wxUnusedVar(lFrom);
327 wxUnusedVar(lTo);
0cf6acbf
DW
328#endif
329} // end of wxComboBox::Remove
0e320a79 330
a5bbd1cc 331void wxComboBox::SetSelection( long lFrom, long lTo )
0e320a79 332{
a5bbd1cc
WS
333 HWND hWnd = GetHwnd();
334 long lFromChar = 0;
335 long lToChar = 0;
0cf6acbf
DW
336
337 //
338 // If from and to are both -1, it means
77ffb593 339 // (in wxWidgets) that all text should be selected.
37f214d5 340 // This translates into Windows convention
0cf6acbf
DW
341 //
342 if ((lFrom == -1L) && (lTo == -1L))
37f214d5 343 {
0cf6acbf
DW
344 lFromChar = 0;
345 lToChar = -1;
37f214d5
DW
346 }
347
0cf6acbf
DW
348 ::WinSendMsg( hWnd
349 ,EM_SETSEL
350 ,MPFROM2SHORT((USHORT)lFromChar, (USHORT)lToChar)
351 ,(MPARAM)0
352 );
353} // end of wxComboBox::SetSelection
354
0cf6acbf
DW
355bool wxComboBox::ProcessEditMsg(
356 WXUINT uMsg
357, WXWPARAM wParam
358, WXLPARAM lParam)
0e320a79 359{
0cf6acbf
DW
360 SHORT vFlag;
361 switch (uMsg)
362 {
363 case WM_CHAR:
364 vFlag = SHORT1FROMMP(wParam);
365 switch(vFlag)
366 {
367 case KC_CHAR:
598d8cac 368 return (HandleChar( wParam
0cf6acbf 369 ,lParam
7d8268a1 370 ,true /* isASCII */
0cf6acbf
DW
371 ));
372
373 case KC_PREVDOWN:
a086de98 374 return (HandleKeyDown( wParam
0cf6acbf
DW
375 ,lParam
376 ));
377
378 case KC_KEYUP:
a086de98 379 return (HandleKeyUp( wParam
0cf6acbf
DW
380 ,lParam
381 ));
382 }
383 break;
598d8cac
DW
384
385 case WM_SETFOCUS:
386 if (SHORT1FROMMP((MPARAM)lParam) == TRUE)
387 return(HandleSetFocus((WXHWND)(HWND)wParam));
388 else
389 return(HandleKillFocus((WXHWND)(HWND)wParam));
0cf6acbf 390 }
7d8268a1 391 return false;
2fbb8fbb 392} // end of wxComboBox::ProcessEditMsg
0cf6acbf
DW
393
394MRESULT EXPENTRY wxComboEditWndProc(
395 HWND hWnd
396, UINT uMessage
397, MPARAM wParam
398, MPARAM lParam
399)
400{
0cf6acbf
DW
401 switch (uMessage)
402 {
403 //
404 // Forward some messages to the combobox
405 //
598d8cac 406 case WM_SETFOCUS:
0cf6acbf
DW
407 case WM_CHAR:
408 {
d804ec69
SN
409 wxComboBox* pCombo = (wxComboBox *)::WinQueryWindowULong( hWnd
410 ,QWL_USER
411 );
0cf6acbf
DW
412
413 if (pCombo->ProcessEditMsg( uMessage
414 ,wParam
415 ,lParam
416 ))
417 return ((MRESULT)0);
418 }
419 break;
420
421 //
422 // TODO: Deal with tooltips here
423 //
424 }
425 return (gfnWndprocEdit(hWnd, (ULONG)uMessage, (MPARAM)wParam, (MPARAM)lParam));
426} // end of wxComboEditWndProc
37f214d5
DW
427
428#endif
429 // wxUSE_COMBOBOX