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