1///////////////////////////////////////////////////////////////////////////// 2// Name: src/os2/combobox.cpp 3// Purpose: wxComboBox class 4// Author: David Webster 5// Modified by: 6// Created: 10/13/99 7// RCS-ID: $Id: combobox.cpp 42872 2006-10-31 20:46:35Z SN $ 8// Copyright: (c) David Webster 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#if wxUSE_COMBOBOX 16 17#include "wx/combobox.h" 18 19#ifndef WX_PRECOMP 20 #include "wx/settings.h" 21#endif 22 23#include "wx/clipbrd.h" 24#include "wx/os2/private.h" 25 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 38IMPLEMENT_DYNAMIC_CLASS(wxComboBox, wxControl) 39 40bool wxComboBox::OS2Command( WXUINT uParam, WXWORD WXUNUSED(wId) ) 41{ 42 long lSel = GetSelection(); 43 wxString sValue; 44 45 switch (uParam) 46 { 47 case CBN_LBSELECT: 48 if (lSel > -1) 49 { 50 wxCommandEvent vEvent( wxEVT_COMMAND_COMBOBOX_SELECTED, GetId() ); 51 52 vEvent.SetInt(lSel); 53 vEvent.SetEventObject(this); 54 vEvent.SetString(GetStringSelection()); 55 56 ProcessCommand(vEvent); 57 } 58 break; 59 60 case CBN_EFCHANGE: 61 { 62 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED, GetId() ); 63 64 if (lSel == -1L) 65 sValue = GetValue(); 66 else 67 sValue = GetStringSelection(); 68 vEvent.SetString(sValue); 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 76 // false from here to pass the message to DefWindowProc() 77 // 78 return false; 79} // end of wxComboBox::OS2Command 80 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 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 108, const wxValidator& rValidator 109, const wxString& rsName 110) 111{ 112 m_isShown = false; 113 114 if (!CreateControl( pParent 115 ,vId 116 ,rPos 117 ,rSize 118 ,lStyle 119 ,rValidator 120 ,rsName 121 )) 122 return false; 123 124 // 125 // Get the right style 126 // 127 long lSstyle = 0L; 128 129 lSstyle = WS_TABSTOP | 130 WS_VISIBLE; 131 132 // clipping siblings does not yet work 133 // if (lStyle & wxCLIP_SIBLINGS ) 134 // lSstyle |= WS_CLIPSIBLINGS; 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 143 if (!OS2CreateControl( _T("COMBOBOX") 144 ,lSstyle 145 )) 146 return false; 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 // 152 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); 153 154 for (int 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 165 // Set height to use with sizers i.e. without the dropdown listbox 166 wxFont vFont = GetFont(); 167 int nEditHeight; 168 wxGetCharSize( GetHWND(), NULL, &nEditHeight, &vFont ); 169 nEditHeight = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nEditHeight); 170 SetInitialSize(wxSize(-1,nEditHeight+4)); // +2x2 for the border 171 172 if (!rsValue.empty()) 173 { 174 SetValue(rsValue); 175 } 176 gfnWndprocEdit = (WXFARPROC)::WinSubclassWindow( (HWND)GetHwnd() 177 ,(PFNWP)wxComboEditWndProc 178 ); 179 ::WinSetWindowULong(GetHwnd(), QWL_USER, (ULONG)this); 180 Show(true); 181 return true; 182} // end of wxComboBox::Create 183 184wxString wxComboBox::GetValue() const 185{ 186 return wxGetWindowText(GetHwnd()); 187} 188 189void wxComboBox::SetValue( 190 const wxString& rsValue 191) 192{ 193 if ( HasFlag(wxCB_READONLY) ) 194 SetStringSelection(rsValue); 195 else 196 ::WinSetWindowText(GetHwnd(), (PSZ)rsValue.c_str()); 197} // end of wxComboBox::SetValue 198 199// 200// Clipboard operations 201// 202void wxComboBox::Copy() 203{ 204 HWND hWnd = GetHwnd(); 205 206 ::WinSendMsg(hWnd, EM_COPY, (MPARAM)0, (MPARAM)0); 207} // end of wxComboBox::Copy 208 209void wxComboBox::Cut() 210{ 211 HWND hWnd = GetHwnd(); 212 213 ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0); 214} // end of wxComboBox::Cut 215 216void wxComboBox::Paste() 217{ 218 HWND hWnd = GetHwnd(); 219 220 ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0); 221} // end of wxComboBox::Paste 222 223void wxComboBox::SetEditable( 224 bool bEditable 225) 226{ 227 HWND hWnd = GetHwnd(); 228 229 ::WinSendMsg(hWnd, EM_SETREADONLY, (MPARAM)!bEditable, (MPARAM)0L); 230} // end of wxComboBox::SetEditable 231 232void wxComboBox::SetInsertionPoint( 233 long lPos 234) 235{ 236 HWND hWnd = GetHwnd(); 237 238 ::WinSendMsg(hWnd, EM_SETFIRSTCHAR, MPFROMLONG(lPos), (MPARAM)0); 239} // end of wxComboBox::SetInsertionPoint 240 241void wxComboBox::SetInsertionPointEnd() 242{ 243 wxTextPos lPos = GetLastPosition(); 244 245 SetInsertionPoint(lPos); 246} // end of wxComboBox::SetInsertionPointEnd 247 248long wxComboBox::GetInsertionPoint() const 249{ 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 259 260wxTextPos wxComboBox::GetLastPosition() const 261{ 262 long lLineLength = 0L; 263 WNDPARAMS vParams; 264 265 // 266 // Get number of characters in the last (only) line. We'll add this to the character 267 // index for the last line, 1st position. 268 // 269 270 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 285void wxComboBox::Replace( long lFrom, 286 long lTo, 287 const wxString& rsValue ) 288{ 289#if wxUSE_CLIPBOARD 290 HWND hWnd = GetHwnd(); 291 292 // 293 // Set selection and remove it 294 // 295 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0); 296 ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0); 297 298 // 299 // Now replace with 'value', by pasting. 300 // 301 wxSetClipboardData( wxDF_TEXT 302 ,(wxObject *)rsValue.c_str() 303 ,0 304 ,0 305 ); 306 307 // 308 // Paste into edit control 309 // 310 ::WinSendMsg(hWnd, EM_PASTE, (MPARAM)0, (MPARAM)0L); 311#else 312 wxUnusedVar(lFrom); 313 wxUnusedVar(lTo); 314 wxUnusedVar(rsValue); 315#endif 316} // end of wxComboBox::Replace 317 318void wxComboBox::Remove( long lFrom, long lTo) 319{ 320#if wxUSE_CLIPBOARD 321 HWND hWnd = GetHwnd(); 322 323 ::WinSendMsg(hWnd, EM_SETSEL, MPFROM2SHORT((USHORT)lFrom, (USHORT)lTo), 0); 324 ::WinSendMsg(hWnd, EM_CUT, (MPARAM)0, (MPARAM)0); 325#else 326 wxUnusedVar(lFrom); 327 wxUnusedVar(lTo); 328#endif 329} // end of wxComboBox::Remove 330 331void wxComboBox::SetSelection( long lFrom, long lTo ) 332{ 333 HWND hWnd = GetHwnd(); 334 long lFromChar = 0; 335 long lToChar = 0; 336 337 // 338 // If from and to are both -1, it means 339 // (in wxWidgets) that all text should be selected. 340 // This translates into Windows convention 341 // 342 if ((lFrom == -1L) && (lTo == -1L)) 343 { 344 lFromChar = 0; 345 lToChar = -1; 346 } 347 348 ::WinSendMsg( hWnd 349 ,EM_SETSEL 350 ,MPFROM2SHORT((USHORT)lFromChar, (USHORT)lToChar) 351 ,(MPARAM)0 352 ); 353} // end of wxComboBox::SetSelection 354 355bool wxComboBox::ProcessEditMsg( 356 WXUINT uMsg 357, WXWPARAM wParam 358, WXLPARAM lParam) 359{ 360 SHORT vFlag; 361 switch (uMsg) 362 { 363 case WM_CHAR: 364 vFlag = SHORT1FROMMP(wParam); 365 switch(vFlag) 366 { 367 case KC_CHAR: 368 return (HandleChar( wParam 369 ,lParam 370 ,true /* isASCII */ 371 )); 372 373 case KC_PREVDOWN: 374 return (HandleKeyDown( wParam 375 ,lParam 376 )); 377 378 case KC_KEYUP: 379 return (HandleKeyUp( wParam 380 ,lParam 381 )); 382 } 383 break; 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)); 390 } 391 return false; 392} // end of wxComboBox::ProcessEditMsg 393 394MRESULT EXPENTRY wxComboEditWndProc( 395 HWND hWnd 396, UINT uMessage 397, MPARAM wParam 398, MPARAM lParam 399) 400{ 401 switch (uMessage) 402 { 403 // 404 // Forward some messages to the combobox 405 // 406 case WM_SETFOCUS: 407 case WM_CHAR: 408 { 409 wxComboBox* pCombo = (wxComboBox *)::WinQueryWindowULong( hWnd 410 ,QWL_USER 411 ); 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 427 428#endif 429 // wxUSE_COMBOBOX 430