ComboBox.cs 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. //
  20. // Copyright (c) 2004-2005 Novell, Inc.
  21. //
  22. // Authors:
  23. // Jordi Mas i Hernandez, [email protected]
  24. //
  25. //
  26. // NOT COMPLETE
  27. using System;
  28. using System.Drawing;
  29. using System.Collections;
  30. using System.ComponentModel;
  31. using System.Reflection;
  32. using System.ComponentModel.Design;
  33. using System.ComponentModel.Design.Serialization;
  34. namespace System.Windows.Forms
  35. {
  36. [DefaultProperty("Items")]
  37. [DefaultEvent("SelectedIndexChanged")]
  38. [Designer ("System.Windows.Forms.Design.ComboBoxDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
  39. public class ComboBox : ListControl
  40. {
  41. private DrawMode draw_mode;
  42. private ComboBoxStyle dropdown_style;
  43. private int dropdown_width;
  44. private const int preferred_height = 20;
  45. private int selected_index;
  46. private object selected_item;
  47. internal ObjectCollection items = null;
  48. private bool suspend_ctrlupdate;
  49. private int maxdrop_items;
  50. private bool integral_height;
  51. private bool sorted;
  52. internal ComboBoxInfo combobox_info;
  53. private readonly int def_button_width = 16;
  54. private bool clicked;
  55. private int max_length;
  56. private ComboListBox listbox_ctrl;
  57. private StringFormat string_format;
  58. private TextBox textbox_ctrl;
  59. private bool process_textchanged_event;
  60. internal class ComboBoxInfo
  61. {
  62. internal int item_height; /* Item's height */
  63. internal Rectangle textarea; /* Rectangle of the editable text area */
  64. internal Rectangle textarea_drawable; /* Rectangle of the editable text area - decorations - button if present*/
  65. internal Rectangle button_rect;
  66. internal bool show_button; /* Is the DropDown button shown? */
  67. internal ButtonState button_status; /* Drop button status */
  68. internal Size listbox_size;
  69. internal Rectangle listbox_area; /* ListBox area in Simple combox, not used in the rest */
  70. internal bool droppeddown; /* Is the associated ListBox dropped down? */
  71. public ComboBoxInfo ()
  72. {
  73. button_status = ButtonState.Normal;
  74. show_button = false;
  75. item_height = 0;
  76. droppeddown = false;
  77. }
  78. }
  79. internal class ComboBoxItem
  80. {
  81. internal int Index;
  82. internal int ItemHeight; /* Only used for OwnerDrawVariable */
  83. public ComboBoxItem (int index)
  84. {
  85. Index = index;
  86. ItemHeight = -1;
  87. }
  88. }
  89. public ComboBox ()
  90. {
  91. items = new ObjectCollection (this);
  92. listbox_ctrl = null;
  93. textbox_ctrl = null;
  94. combobox_info = new ComboBoxInfo ();
  95. combobox_info.item_height = FontHeight + 2;
  96. DropDownStyle = ComboBoxStyle.DropDown;
  97. BackColor = ThemeEngine.Current.ColorWindow;
  98. draw_mode = DrawMode.Normal;
  99. selected_index = -1;
  100. selected_item = null;
  101. maxdrop_items = 8;
  102. suspend_ctrlupdate = false;
  103. clicked = false;
  104. dropdown_width = -1;
  105. max_length = 0;
  106. integral_height = true;
  107. process_textchanged_event = true;
  108. string_format = new StringFormat ();
  109. /* Events */
  110. MouseDown += new MouseEventHandler (OnMouseDownCB);
  111. MouseUp += new MouseEventHandler (OnMouseUpCB);
  112. MouseMove += new MouseEventHandler (OnMouseMoveCB);
  113. }
  114. #region events
  115. [Browsable (false)]
  116. [EditorBrowsable (EditorBrowsableState.Never)]
  117. public new event EventHandler BackgroundImageChanged;
  118. public event DrawItemEventHandler DrawItem;
  119. public event EventHandler DropDown;
  120. public event EventHandler DropDownStyleChanged;
  121. public event MeasureItemEventHandler MeasureItem;
  122. [Browsable (false)]
  123. [EditorBrowsable (EditorBrowsableState.Never)]
  124. public new event PaintEventHandler Paint;
  125. public event EventHandler SelectedIndexChanged;
  126. public event EventHandler SelectionChangeCommitted;
  127. #endregion Events
  128. #region Public Properties
  129. public override Color BackColor {
  130. get { return base.BackColor; }
  131. set {
  132. if (base.BackColor == value)
  133. return;
  134. base.BackColor = value;
  135. Refresh ();
  136. }
  137. }
  138. [Browsable (false)]
  139. [EditorBrowsable (EditorBrowsableState.Never)]
  140. public override Image BackgroundImage {
  141. get { return base.BackgroundImage; }
  142. set {
  143. if (base.BackgroundImage == value)
  144. return;
  145. base.BackgroundImage = value;
  146. if (BackgroundImageChanged != null)
  147. BackgroundImageChanged (this, EventArgs.Empty);
  148. Refresh ();
  149. }
  150. }
  151. protected override CreateParams CreateParams {
  152. get { return base.CreateParams;}
  153. }
  154. protected override Size DefaultSize {
  155. get { return new Size (121, PreferredHeight); }
  156. }
  157. [RefreshProperties(RefreshProperties.Repaint)]
  158. [DefaultValue (DrawMode.Normal)]
  159. public DrawMode DrawMode {
  160. get { return draw_mode; }
  161. set {
  162. if (!Enum.IsDefined (typeof (DrawMode), value))
  163. throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
  164. if (draw_mode == value)
  165. return;
  166. draw_mode = value;
  167. Refresh ();
  168. }
  169. }
  170. [DefaultValue (ComboBoxStyle.DropDown)]
  171. [RefreshProperties(RefreshProperties.Repaint)]
  172. public ComboBoxStyle DropDownStyle {
  173. get { return dropdown_style; }
  174. set {
  175. if (!Enum.IsDefined (typeof (ComboBoxStyle), value))
  176. throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ComboBoxStyle", value));
  177. if (dropdown_style == value)
  178. return;
  179. if (dropdown_style == ComboBoxStyle.Simple) {
  180. if (listbox_ctrl != null) {
  181. listbox_ctrl.Dispose ();
  182. Controls.Remove (listbox_ctrl);
  183. listbox_ctrl = null;
  184. }
  185. }
  186. if (dropdown_style != ComboBoxStyle.DropDownList && value == ComboBoxStyle.DropDownList) {
  187. if (textbox_ctrl != null) {
  188. Controls.Remove (textbox_ctrl);
  189. textbox_ctrl.Dispose ();
  190. textbox_ctrl = null;
  191. }
  192. }
  193. dropdown_style = value;
  194. if (dropdown_style == ComboBoxStyle.Simple) {
  195. CBoxInfo.show_button = false;
  196. CreateComboListBox ();
  197. Controls.Add (listbox_ctrl);
  198. }
  199. else {
  200. CBoxInfo.show_button = true;
  201. CBoxInfo.button_status = ButtonState.Normal;
  202. }
  203. if (dropdown_style != ComboBoxStyle.DropDownList && textbox_ctrl == null) {
  204. textbox_ctrl = new TextBox ();
  205. textbox_ctrl.TextChanged += new EventHandler (OnTextChangedEdit);
  206. Controls.Add (textbox_ctrl);
  207. }
  208. if (DropDownStyleChanged != null)
  209. DropDownStyleChanged (this, EventArgs.Empty);
  210. CalcTextArea ();
  211. Refresh ();
  212. }
  213. }
  214. public int DropDownWidth {
  215. get {
  216. if (dropdown_width == -1)
  217. return Width;
  218. return dropdown_width;
  219. }
  220. set {
  221. if (dropdown_width == value)
  222. return;
  223. if (value < 1)
  224. throw new ArgumentException ("The DropDownWidth value is less than one");
  225. dropdown_width = value;
  226. }
  227. }
  228. [Browsable (false)]
  229. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  230. public bool DroppedDown {
  231. get {
  232. if (dropdown_style == ComboBoxStyle.Simple)
  233. return true;
  234. return CBoxInfo.droppeddown;
  235. }
  236. set {
  237. if (dropdown_style == ComboBoxStyle.Simple)
  238. return;
  239. if (value == true) {
  240. DropDownListBox ();
  241. }
  242. else {
  243. listbox_ctrl.Hide ();
  244. }
  245. if (DropDown != null)
  246. DropDown (this, EventArgs.Empty);
  247. }
  248. }
  249. public override bool Focused {
  250. get { return base.Focused; }
  251. }
  252. public override Color ForeColor {
  253. get { return base.ForeColor; }
  254. set {
  255. if (base.ForeColor == value)
  256. return;
  257. base.ForeColor = value;
  258. Refresh ();
  259. }
  260. }
  261. [DefaultValue (true)]
  262. [Localizable (true)]
  263. public bool IntegralHeight {
  264. get { return integral_height; }
  265. set {
  266. if (integral_height == value)
  267. return;
  268. integral_height = value;
  269. Refresh ();
  270. }
  271. }
  272. [Localizable (true)]
  273. public virtual int ItemHeight {
  274. get { return combobox_info.item_height; }
  275. set {
  276. if (value < 0)
  277. throw new ArgumentOutOfRangeException ("The item height value is less than zero");
  278. combobox_info.item_height = value;
  279. CalcTextArea ();
  280. Refresh ();
  281. }
  282. }
  283. [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
  284. [Localizable (true)]
  285. [Editor ("System.Windows.Forms.Design.ListContolStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
  286. public ComboBox.ObjectCollection Items {
  287. get { return items; }
  288. }
  289. [DefaultValue (8)]
  290. [Localizable (true)]
  291. public int MaxDropDownItems {
  292. get { return maxdrop_items; }
  293. set {
  294. if (maxdrop_items == value)
  295. return;
  296. maxdrop_items = value;
  297. }
  298. }
  299. [DefaultValue (32767)]
  300. [Localizable (true)]
  301. public int MaxLength {
  302. get { return max_length; }
  303. set {
  304. if (max_length == value)
  305. return;
  306. max_length = value;
  307. if (dropdown_style != ComboBoxStyle.DropDownList) {
  308. if (value < 0) {
  309. value = 0;
  310. }
  311. textbox_ctrl.MaxLength = value;
  312. }
  313. }
  314. }
  315. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  316. [Browsable (false)]
  317. public int PreferredHeight {
  318. get { return preferred_height; }
  319. }
  320. [Browsable (false)]
  321. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  322. public override int SelectedIndex {
  323. get { return selected_index; }
  324. set {
  325. if (value < -2 || value >= Items.Count)
  326. throw new ArgumentOutOfRangeException ("Index of out range");
  327. if (selected_index == value)
  328. return;
  329. selected_index = value;
  330. if (dropdown_style != ComboBoxStyle.DropDownList) {
  331. SetControlText (Items[selected_index].ToString ());
  332. }
  333. OnSelectedIndexChanged (new EventArgs ());
  334. Refresh ();
  335. }
  336. }
  337. [Browsable (false)]
  338. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  339. [Bindable(true)]
  340. public object SelectedItem {
  341. get {
  342. if (selected_index !=-1 && Items !=null && Items.Count > 0)
  343. return Items[selected_index];
  344. else
  345. return null;
  346. }
  347. set {
  348. if (selected_item == value)
  349. return;
  350. int index = Items.IndexOf (value);
  351. if (index == -1)
  352. return;
  353. selected_index = index;
  354. if (dropdown_style != ComboBoxStyle.DropDownList) {
  355. SetControlText (Items[selected_index].ToString ());
  356. }
  357. OnSelectedItemChanged (new EventArgs ());
  358. Refresh ();
  359. }
  360. }
  361. [Localizable (true)]
  362. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  363. public string SelectedText {
  364. get {
  365. if (dropdown_style == ComboBoxStyle.DropDownList)
  366. return "";
  367. return textbox_ctrl.Text;
  368. }
  369. set {
  370. if (dropdown_style == ComboBoxStyle.DropDownList)
  371. return;
  372. if (textbox_ctrl.Text == value)
  373. return;
  374. textbox_ctrl.SelectedText = value;
  375. }
  376. }
  377. [Browsable (false)]
  378. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  379. public int SelectionLength {
  380. get {
  381. if (dropdown_style == ComboBoxStyle.DropDownList)
  382. return 0;
  383. return textbox_ctrl.SelectionLength;
  384. }
  385. set {
  386. if (dropdown_style == ComboBoxStyle.DropDownList)
  387. return;
  388. if (textbox_ctrl.SelectionLength == value)
  389. return;
  390. textbox_ctrl.SelectionLength = value;
  391. }
  392. }
  393. [Browsable (false)]
  394. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  395. public int SelectionStart {
  396. get {
  397. if (dropdown_style == ComboBoxStyle.DropDownList)
  398. return 0;
  399. return textbox_ctrl.SelectionStart;
  400. }
  401. set {
  402. if (dropdown_style == ComboBoxStyle.DropDownList)
  403. return;
  404. if (textbox_ctrl.SelectionStart == value)
  405. return;
  406. textbox_ctrl.SelectionStart = value;
  407. }
  408. }
  409. [DefaultValue (false)]
  410. public bool Sorted {
  411. get { return sorted; }
  412. set {
  413. if (sorted == value)
  414. return;
  415. sorted = value;
  416. }
  417. }
  418. [Bindable (true)]
  419. [Browsable (true)]
  420. public override string Text {
  421. get {
  422. if (SelectedItem != null)
  423. return SelectedItem.ToString ();
  424. return base.Text;
  425. }
  426. set {
  427. if (value == null) {
  428. SelectedIndex = -1;
  429. return;
  430. }
  431. int index = FindString (value);
  432. if (index != -1) {
  433. SelectedIndex = -1;
  434. return;
  435. }
  436. if (dropdown_style != ComboBoxStyle.DropDownList) {
  437. textbox_ctrl.Text = value.ToString ();
  438. }
  439. }
  440. }
  441. #endregion Public Properties
  442. #region Private Properties
  443. internal ComboBoxInfo CBoxInfo {
  444. get { return combobox_info; }
  445. }
  446. #endregion Private Properties
  447. #region Public Methods
  448. protected virtual void AddItemsCore (object[] value)
  449. {
  450. }
  451. public void BeginUpdate ()
  452. {
  453. suspend_ctrlupdate = true;
  454. }
  455. protected override void Dispose (bool disposing)
  456. {
  457. if (disposing == true) {
  458. if (listbox_ctrl != null) {
  459. listbox_ctrl.Dispose ();
  460. Controls.Remove (listbox_ctrl);
  461. listbox_ctrl = null;
  462. }
  463. if (textbox_ctrl != null) {
  464. Controls.Remove (textbox_ctrl);
  465. textbox_ctrl.Dispose ();
  466. textbox_ctrl = null;
  467. }
  468. }
  469. base.Dispose (disposing);
  470. }
  471. public void EndUpdate ()
  472. {
  473. suspend_ctrlupdate = false;
  474. UpdatedItems ();
  475. }
  476. public int FindString (string s)
  477. {
  478. return FindString (s, 0);
  479. }
  480. public int FindString (string s, int startIndex)
  481. {
  482. for (int i = startIndex; i < Items.Count; i++) {
  483. if ((Items[i].ToString ()).StartsWith (s))
  484. return i;
  485. }
  486. return -1;
  487. }
  488. public int FindStringExact (string s)
  489. {
  490. return FindStringExact (s, 0);
  491. }
  492. public int FindStringExact (string s, int startIndex)
  493. {
  494. for (int i = startIndex; i < Items.Count; i++) {
  495. if ((Items[i].ToString ()).Equals (s))
  496. return i;
  497. }
  498. return -1;
  499. }
  500. public int GetItemHeight (int index)
  501. {
  502. if (index < 0 || index >= Items.Count )
  503. throw new ArgumentOutOfRangeException ("The item height value is less than zero");
  504. if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated == true) {
  505. if ((Items.GetComboBoxItem (index)).ItemHeight != -1) {
  506. return (Items.GetComboBoxItem (index)).ItemHeight;
  507. }
  508. MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
  509. OnMeasureItem (args);
  510. (Items.GetComboBoxItem (index)).ItemHeight = args.ItemHeight;
  511. return args.ItemHeight;
  512. }
  513. return ItemHeight;
  514. }
  515. protected override bool IsInputKey (Keys keyData)
  516. {
  517. switch (keyData) {
  518. case Keys.Up:
  519. case Keys.Down:
  520. case Keys.PageUp:
  521. case Keys.PageDown:
  522. return true;
  523. default:
  524. return false;
  525. }
  526. }
  527. protected override void OnBackColorChanged (EventArgs e)
  528. {
  529. base.OnBackColorChanged (e);
  530. }
  531. protected override void OnDataSourceChanged (EventArgs e)
  532. {
  533. base.OnDataSourceChanged (e);
  534. }
  535. protected override void OnDisplayMemberChanged (EventArgs e)
  536. {
  537. base.OnDisplayMemberChanged (e);
  538. }
  539. protected virtual void OnDrawItem (DrawItemEventArgs e)
  540. {
  541. if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable)) {
  542. DrawItem (this, e);
  543. return;
  544. }
  545. Color back_color, fore_color;
  546. Rectangle text_draw = e.Bounds;
  547. if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
  548. back_color = ThemeEngine.Current.ColorHilight;
  549. fore_color = ThemeEngine.Current.ColorHilightText;
  550. }
  551. else {
  552. back_color = e.BackColor;
  553. fore_color = e.ForeColor;
  554. }
  555. e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (back_color), e.Bounds);
  556. if (e.Index != -1) {
  557. e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
  558. ThemeEngine.Current.ResPool.GetSolidBrush (fore_color),
  559. text_draw, string_format);
  560. }
  561. if ((e.State & DrawItemState.Focus) == DrawItemState.Focus) {
  562. ThemeEngine.Current.CPDrawFocusRectangle (e.Graphics, e.Bounds, fore_color, back_color);
  563. }
  564. }
  565. protected virtual void OnDropDown (EventArgs e)
  566. {
  567. if (DropDown != null)
  568. DropDown (this, e);
  569. }
  570. protected virtual void OnDropDownStyleChanged (EventArgs e)
  571. {
  572. if (DropDownStyleChanged != null)
  573. DropDownStyleChanged (this, e);
  574. }
  575. protected override void OnFontChanged (EventArgs e)
  576. {
  577. base.OnFontChanged (e);
  578. if (textbox_ctrl != null) {
  579. textbox_ctrl.Font = Font;
  580. }
  581. combobox_info.item_height = FontHeight + 2;
  582. CalcTextArea ();
  583. }
  584. protected override void OnForeColorChanged (EventArgs e)
  585. {
  586. base.OnForeColorChanged (e);
  587. }
  588. protected override void OnHandleCreated (EventArgs e)
  589. {
  590. base.OnHandleCreated (e);
  591. CalcTextArea ();
  592. }
  593. protected override void OnHandleDestroyed (EventArgs e)
  594. {
  595. base.OnHandleDestroyed (e);
  596. }
  597. protected override void OnKeyPress (KeyPressEventArgs e)
  598. {
  599. base.OnKeyPress (e);
  600. }
  601. protected virtual void OnMeasureItem (MeasureItemEventArgs e)
  602. {
  603. if (MeasureItem != null)
  604. MeasureItem (this, e);
  605. }
  606. protected override void OnParentBackColorChanged (EventArgs e)
  607. {
  608. base.OnParentBackColorChanged (e);
  609. }
  610. protected override void OnResize (EventArgs e)
  611. {
  612. base.OnResize (e);
  613. CalcTextArea ();
  614. }
  615. protected override void OnSelectedIndexChanged (EventArgs e)
  616. {
  617. base.OnSelectedIndexChanged (e);
  618. if (SelectedIndexChanged != null)
  619. SelectedIndexChanged (this, e);
  620. }
  621. protected virtual void OnSelectedItemChanged (EventArgs e)
  622. {
  623. if (SelectedIndexChanged != null)
  624. SelectedIndexChanged (this, e);
  625. }
  626. protected override void OnSelectedValueChanged (EventArgs e)
  627. {
  628. base.OnSelectedValueChanged (e);
  629. }
  630. protected virtual void OnSelectionChangeCommitted (EventArgs e)
  631. {
  632. if (SelectionChangeCommitted != null)
  633. SelectionChangeCommitted (this, e);
  634. }
  635. protected override void RefreshItem (int index)
  636. {
  637. if (index < 0 || index >= Items.Count)
  638. throw new ArgumentOutOfRangeException ("Index of out range");
  639. if (draw_mode == DrawMode.OwnerDrawVariable) {
  640. (Items.GetComboBoxItem (index)).ItemHeight = -1;
  641. }
  642. }
  643. public void Select (int start, int lenght)
  644. {
  645. if (start < 0)
  646. throw new ArgumentException ("Start cannot be less than zero");
  647. if (lenght < 0)
  648. throw new ArgumentException ("Start cannot be less than zero");
  649. if (dropdown_style == ComboBoxStyle.DropDownList)
  650. return;
  651. textbox_ctrl.Select (start, lenght);
  652. }
  653. public void SelectAll ()
  654. {
  655. if (dropdown_style == ComboBoxStyle.DropDownList)
  656. return;
  657. textbox_ctrl.SelectAll ();
  658. }
  659. protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
  660. {
  661. base.SetBoundsCore (x, y, width, height, specified);
  662. }
  663. protected override void SetItemCore (int index, object value)
  664. {
  665. if (index < 0 || index >= Items.Count)
  666. return;
  667. Items[index] = value;
  668. }
  669. protected override void SetItemsCore (IList value)
  670. {
  671. Items.AddRange (value);
  672. }
  673. public override string ToString ()
  674. {
  675. return base.ToString () + ", Items.Count:" + Items.Count;
  676. }
  677. protected override void WndProc (ref Message m)
  678. {
  679. switch ((Msg) m.Msg) {
  680. case Msg.WM_PAINT: {
  681. PaintEventArgs paint_event;
  682. paint_event = XplatUI.PaintEventStart (Handle);
  683. OnPaintCB (paint_event);
  684. XplatUI.PaintEventEnd (Handle);
  685. return;
  686. }
  687. case Msg.WM_ERASEBKGND:
  688. m.Result = (IntPtr) 1;
  689. return;
  690. default:
  691. break;
  692. }
  693. base.WndProc (ref m);
  694. }
  695. #endregion Public Methods
  696. #region Private Methods
  697. // Calcs the text area size
  698. internal void CalcTextArea ()
  699. {
  700. combobox_info.textarea = ClientRectangle;
  701. /* Edit area */
  702. combobox_info.textarea.Height = ItemHeight + ThemeEngine.Current.DrawComboBoxEditDecorationTop () +
  703. ThemeEngine.Current.DrawComboBoxEditDecorationBottom () + 2;
  704. // TODO: Does the +2 change at different font resolutions?
  705. /* Edit area - minus decorations (text drawable area) */
  706. combobox_info.textarea_drawable = combobox_info.textarea;
  707. combobox_info.textarea_drawable.Y += ThemeEngine.Current.DrawComboBoxEditDecorationTop ();
  708. combobox_info.textarea_drawable.X += ThemeEngine.Current.DrawComboBoxEditDecorationLeft ();
  709. combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationBottom ();
  710. combobox_info.textarea_drawable.Height -= ThemeEngine.Current.DrawComboBoxEditDecorationTop();
  711. combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationRight ();
  712. combobox_info.textarea_drawable.Width -= ThemeEngine.Current.DrawComboBoxEditDecorationLeft ();
  713. /* Non-drawable area */
  714. Region area = new Region (ClientRectangle);
  715. area.Exclude (combobox_info.textarea);
  716. RectangleF bounds = area.GetBounds (DeviceContext);
  717. combobox_info.listbox_area = new Rectangle ((int)bounds.X, (int)bounds.Y,
  718. (int)bounds.Width, (int)bounds.Height);
  719. if (CBoxInfo.show_button) {
  720. combobox_info.textarea_drawable.Width -= def_button_width;
  721. combobox_info.button_rect = new Rectangle (combobox_info.textarea_drawable.X + combobox_info.textarea_drawable.Width,
  722. combobox_info.textarea_drawable.Y, def_button_width, combobox_info.textarea_drawable.Height);
  723. }
  724. if (dropdown_style != ComboBoxStyle.DropDownList) { /* There is an edit control*/
  725. if (textbox_ctrl != null) {
  726. textbox_ctrl.Location = new Point (combobox_info.textarea_drawable.X, combobox_info.textarea_drawable.Y);
  727. textbox_ctrl.Size = new Size (combobox_info.textarea_drawable.Width, combobox_info.textarea_drawable.Height);
  728. }
  729. }
  730. if (listbox_ctrl != null && dropdown_style == ComboBoxStyle.Simple) {
  731. listbox_ctrl.Location = new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
  732. combobox_info.textarea.Height);
  733. listbox_ctrl.CalcListBoxArea ();
  734. }
  735. }
  736. private void CreateComboListBox ()
  737. {
  738. listbox_ctrl = new ComboListBox (this);
  739. }
  740. internal void Draw (Rectangle clip)
  741. {
  742. // No edit control, we paint the edit ourselfs
  743. if (dropdown_style == ComboBoxStyle.DropDownList) {
  744. DrawItemState state = DrawItemState.None;
  745. Rectangle item_rect = combobox_info.textarea_drawable;
  746. item_rect.Height = ItemHeight + 2;
  747. if (CBoxInfo.droppeddown == false) {
  748. state = DrawItemState.Focus |DrawItemState.Selected;
  749. }
  750. OnDrawItem (new DrawItemEventArgs (DeviceContext, Font, item_rect,
  751. selected_index, state, ForeColor, BackColor));
  752. }
  753. if (clip.IntersectsWith (combobox_info.listbox_area) == true) {
  754. DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor),
  755. combobox_info.listbox_area);
  756. }
  757. if (CBoxInfo.show_button) {
  758. DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorButtonFace),
  759. combobox_info.button_rect);
  760. ThemeEngine.Current.CPDrawComboButton (DeviceContext,
  761. combobox_info.button_rect, combobox_info.button_status);
  762. }
  763. ThemeEngine.Current.DrawComboBoxEditDecorations (DeviceContext, this, combobox_info.textarea);
  764. }
  765. internal void DropDownListBox ()
  766. {
  767. if (DropDownStyle == ComboBoxStyle.Simple)
  768. return;
  769. if (listbox_ctrl == null) {
  770. CreateComboListBox ();
  771. }
  772. listbox_ctrl.Location = PointToScreen (new Point (combobox_info.textarea.X, combobox_info.textarea.Y +
  773. combobox_info.textarea.Height));
  774. if (listbox_ctrl.ShowWindow () == true) {
  775. CBoxInfo.droppeddown = true;
  776. }
  777. combobox_info.button_status = ButtonState.Pushed;
  778. if (dropdown_style == ComboBoxStyle.DropDownList) {
  779. Invalidate (combobox_info.textarea_drawable);
  780. }
  781. }
  782. internal void DropDownListBoxFinished ()
  783. {
  784. if (DropDownStyle == ComboBoxStyle.Simple)
  785. return;
  786. combobox_info.button_status = ButtonState.Normal;
  787. Invalidate (combobox_info.button_rect);
  788. CBoxInfo.droppeddown = false;
  789. clicked = false;
  790. }
  791. private int FindStringCaseInsensitive (string search)
  792. {
  793. for (int i = 0; i < Items.Count; i++)
  794. {
  795. if (String.Compare (Items[i].ToString (), 0, search, 0, search.Length, true) == 0)
  796. return i;
  797. }
  798. return -1;
  799. }
  800. internal virtual void OnMouseDownCB (object sender, MouseEventArgs e)
  801. {
  802. /* Click On button*/
  803. Rectangle hit_rect;
  804. if (dropdown_style == ComboBoxStyle.DropDownList) {
  805. hit_rect = combobox_info.textarea;
  806. } else {
  807. hit_rect = combobox_info.button_rect;
  808. }
  809. if (hit_rect.Contains (e.X, e.Y)) {
  810. if (clicked == false) {
  811. clicked = true;
  812. DropDownListBox ();
  813. } else {
  814. listbox_ctrl.Hide ();
  815. DropDownListBoxFinished ();
  816. }
  817. Invalidate (combobox_info.button_rect);
  818. }
  819. }
  820. internal virtual void OnMouseMoveCB (object sender, MouseEventArgs e)
  821. {
  822. /* When there are no items, act as a regular button */
  823. if (clicked == true && Items.Count == 0 &&
  824. combobox_info.button_rect.Contains (e.X, e.Y) == false) {
  825. DropDownListBoxFinished ();
  826. }
  827. }
  828. internal virtual void OnMouseUpCB (object sender, MouseEventArgs e)
  829. {
  830. /* Click on button*/
  831. if (clicked == true && combobox_info.button_rect.Contains (e.X, e.Y)) {
  832. DropDownListBoxFinished ();
  833. }
  834. }
  835. private void OnPaintCB (PaintEventArgs pevent)
  836. {
  837. if (Width <= 0 || Height <= 0 || Visible == false || suspend_ctrlupdate == true)
  838. return;
  839. /* Copies memory drawing buffer to screen*/
  840. Draw (ClientRectangle);
  841. pevent.Graphics.DrawImage (ImageBuffer, ClientRectangle, ClientRectangle, GraphicsUnit.Pixel);
  842. if (Paint != null)
  843. Paint (this, pevent);
  844. }
  845. private void OnTextChangedEdit (object sender, EventArgs e)
  846. {
  847. if (process_textchanged_event == false)
  848. return;
  849. int item = FindStringCaseInsensitive (textbox_ctrl.Text);
  850. if (item == -1)
  851. return;
  852. listbox_ctrl.SetTopItem (item);
  853. listbox_ctrl.SetHighLightedItem (item);
  854. }
  855. internal void SetControlText (string s)
  856. {
  857. process_textchanged_event = false;
  858. textbox_ctrl.Text = s;
  859. process_textchanged_event = true;
  860. }
  861. private void UpdatedItems ()
  862. {
  863. if (dropdown_style != ComboBoxStyle.Simple)
  864. return;
  865. listbox_ctrl.UpdateLastVisibleItem ();
  866. listbox_ctrl.CalcListBoxArea ();
  867. listbox_ctrl.Refresh ();
  868. }
  869. #endregion Private Methods
  870. /*
  871. ComboBox.ObjectCollection
  872. */
  873. [ListBindableAttribute (false)]
  874. public class ObjectCollection : IList, ICollection, IEnumerable
  875. {
  876. private ComboBox owner;
  877. internal ArrayList object_items = new ArrayList ();
  878. internal ArrayList combobox_items = new ArrayList ();
  879. public ObjectCollection (ComboBox owner)
  880. {
  881. this.owner = owner;
  882. }
  883. #region Public Properties
  884. public virtual int Count {
  885. get { return object_items.Count; }
  886. }
  887. public virtual bool IsReadOnly {
  888. get { return false; }
  889. }
  890. public virtual object this [int index] {
  891. get {
  892. if (index < 0 || index >= Count)
  893. throw new ArgumentOutOfRangeException ("Index of out range");
  894. return object_items[index];
  895. }
  896. set {
  897. if (index < 0 || index >= Count)
  898. throw new ArgumentOutOfRangeException ("Index of out range");
  899. object_items[index] = value;
  900. }
  901. }
  902. bool ICollection.IsSynchronized {
  903. get { return false; }
  904. }
  905. object ICollection.SyncRoot {
  906. get { return this; }
  907. }
  908. bool IList.IsFixedSize {
  909. get { return false; }
  910. }
  911. #endregion Public Properties
  912. #region Private Properties
  913. internal ArrayList ObjectItems {
  914. get { return object_items;}
  915. set {
  916. object_items = value;
  917. }
  918. }
  919. internal ArrayList ListBoxItems {
  920. get { return combobox_items;}
  921. set {
  922. combobox_items = value;
  923. }
  924. }
  925. #endregion Private Properties
  926. #region Public Methods
  927. public int Add (object item)
  928. {
  929. int idx;
  930. idx = AddItem (item);
  931. owner.UpdatedItems ();
  932. return idx;
  933. }
  934. public void AddRange (object[] items)
  935. {
  936. foreach (object mi in items)
  937. AddItem (mi);
  938. owner.UpdatedItems ();
  939. }
  940. public virtual void Clear ()
  941. {
  942. object_items.Clear ();
  943. combobox_items.Clear ();
  944. owner.UpdatedItems ();
  945. owner.selected_index = -1;
  946. }
  947. public virtual bool Contains (object obj)
  948. {
  949. return object_items.Contains (obj);
  950. }
  951. public void CopyTo (object[] dest, int arrayIndex)
  952. {
  953. object_items.CopyTo (dest, arrayIndex);
  954. }
  955. void ICollection.CopyTo (Array dest, int index)
  956. {
  957. object_items.CopyTo (dest, index);
  958. }
  959. public virtual IEnumerator GetEnumerator ()
  960. {
  961. return object_items.GetEnumerator ();
  962. }
  963. int IList.Add (object item)
  964. {
  965. return Add (item);
  966. }
  967. public virtual int IndexOf (object value)
  968. {
  969. return object_items.IndexOf (value);
  970. }
  971. public virtual void Insert (int index, object item)
  972. {
  973. if (index < 0 || index >= Count)
  974. throw new ArgumentOutOfRangeException ("Index of out range");
  975. ObjectCollection new_items = new ObjectCollection (owner);
  976. object sel_item = owner.SelectedItem;
  977. owner.BeginUpdate ();
  978. for (int i = 0; i < index; i++) {
  979. new_items.AddItem (ObjectItems[i]);
  980. }
  981. new_items.AddItem (item);
  982. for (int i = index; i < Count; i++){
  983. new_items.AddItem (ObjectItems[i]);
  984. }
  985. ObjectItems = new_items.ObjectItems;
  986. ListBoxItems = new_items.ListBoxItems;
  987. if (sel_item != null) {
  988. int idx = IndexOf (sel_item);
  989. owner.selected_index = idx;
  990. owner.listbox_ctrl.SetHighLightedItem (idx);
  991. }
  992. owner.EndUpdate (); // Calls UpdateItemInfo
  993. }
  994. public virtual void Remove (object value)
  995. {
  996. RemoveAt (IndexOf (value));
  997. }
  998. public virtual void RemoveAt (int index)
  999. {
  1000. if (index < 0 || index >= Count)
  1001. throw new ArgumentOutOfRangeException ("Index of out range");
  1002. object_items.RemoveAt (index);
  1003. combobox_items.RemoveAt (index);
  1004. owner.UpdatedItems ();
  1005. }
  1006. #endregion Public Methods
  1007. #region Private Methods
  1008. private int AddItem (object item)
  1009. {
  1010. int cnt = object_items.Count;
  1011. object_items.Add (item);
  1012. combobox_items.Add (new ComboBox.ComboBoxItem (cnt));
  1013. return cnt;
  1014. }
  1015. internal void AddRange (IList items)
  1016. {
  1017. foreach (object mi in items)
  1018. AddItem (mi);
  1019. owner.UpdatedItems ();
  1020. }
  1021. internal ComboBox.ComboBoxItem GetComboBoxItem (int index)
  1022. {
  1023. if (index < 0 || index >= Count)
  1024. throw new ArgumentOutOfRangeException ("Index of out range");
  1025. return (ComboBox.ComboBoxItem) combobox_items[index];
  1026. }
  1027. internal void SetComboBoxItem (ComboBox.ComboBoxItem item, int index)
  1028. {
  1029. if (index < 0 || index >= Count)
  1030. throw new ArgumentOutOfRangeException ("Index of out range");
  1031. combobox_items[index] = item;
  1032. }
  1033. #endregion Private Methods
  1034. }
  1035. /*
  1036. class ComboListBox
  1037. */
  1038. internal class ComboListBox : Control
  1039. {
  1040. private ComboBox owner;
  1041. private VScrollBarLB vscrollbar_ctrl;
  1042. private int top_item; /* First item that we show the in the current page */
  1043. private int last_item; /* Last visible item */
  1044. private int highlighted_item; /* Item that is currently selected */
  1045. internal int page_size; /* Number of listbox items per page */
  1046. private Rectangle textarea_drawable; /* Rectangle of the drawable text area */
  1047. internal enum ItemNavigation
  1048. {
  1049. First,
  1050. Last,
  1051. Next,
  1052. Previous,
  1053. NextPage,
  1054. PreviousPage,
  1055. }
  1056. class VScrollBarLB : VScrollBar
  1057. {
  1058. public VScrollBarLB ()
  1059. {
  1060. }
  1061. public void FireMouseDown (MouseEventArgs e)
  1062. {
  1063. OnMouseDown (e);
  1064. }
  1065. public void FireMouseUp (MouseEventArgs e)
  1066. {
  1067. OnMouseUp (e);
  1068. }
  1069. public void FireMouseMove (MouseEventArgs e)
  1070. {
  1071. OnMouseMove (e);
  1072. }
  1073. }
  1074. public ComboListBox (ComboBox owner) : base ()
  1075. {
  1076. this.owner = owner;
  1077. top_item = 0;
  1078. last_item = 0;
  1079. page_size = 0;
  1080. highlighted_item = -1;
  1081. MouseDown += new MouseEventHandler (OnMouseDownPUW);
  1082. MouseUp += new MouseEventHandler (OnMouseUpPUW);
  1083. MouseMove += new MouseEventHandler (OnMouseMovePUW);
  1084. KeyDown += new KeyEventHandler (OnKeyDownPUW);
  1085. Paint += new PaintEventHandler (OnPaintPUW);
  1086. SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
  1087. SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);
  1088. }
  1089. protected override CreateParams CreateParams
  1090. {
  1091. get {
  1092. CreateParams cp = base.CreateParams;
  1093. if (owner != null && owner.DropDownStyle != ComboBoxStyle.Simple) {
  1094. cp.Style = unchecked ((int)(WindowStyles.WS_POPUP | WindowStyles.WS_VISIBLE | WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN));
  1095. cp.ExStyle |= (int)(WindowStyles.WS_EX_TOOLWINDOW | WindowStyles.WS_EX_TOPMOST);
  1096. }
  1097. return cp;
  1098. }
  1099. }
  1100. #region Private Methods
  1101. protected override void CreateHandle ()
  1102. {
  1103. base.CreateHandle ();
  1104. }
  1105. // Calcs the listbox area
  1106. internal void CalcListBoxArea ()
  1107. {
  1108. int width, height;
  1109. int item_height = owner.ItemHeight;
  1110. if (owner.DropDownStyle == ComboBoxStyle.Simple) {
  1111. width = owner.CBoxInfo.listbox_area.Width;
  1112. height = owner.CBoxInfo.listbox_area.Height;
  1113. if (owner.IntegralHeight == true) {
  1114. int remaining = (height -
  1115. ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
  1116. ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle)) %
  1117. (item_height - 2);
  1118. if (remaining > 0) {
  1119. height -= remaining;
  1120. }
  1121. }
  1122. }
  1123. else { // DropDown or DropDownList
  1124. width = owner.DropDownWidth;
  1125. int count = (owner.Items.Count <= owner.MaxDropDownItems) ? owner.Items.Count : owner.MaxDropDownItems;
  1126. if (owner.DrawMode == DrawMode.OwnerDrawVariable) {
  1127. height = 0;
  1128. for (int i = 0; i < count; i++) {
  1129. height += owner.GetItemHeight (i);
  1130. }
  1131. } else {
  1132. height = (item_height - 2) * count;
  1133. }
  1134. height += ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);
  1135. height += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
  1136. }
  1137. if (owner.Items.Count <= owner.MaxDropDownItems) {
  1138. /* Does not need vertical scrollbar*/
  1139. if (vscrollbar_ctrl != null) {
  1140. vscrollbar_ctrl.Dispose ();
  1141. Controls.Remove (vscrollbar_ctrl);
  1142. vscrollbar_ctrl = null;
  1143. }
  1144. }
  1145. else {
  1146. /* Need vertical scrollbar */
  1147. vscrollbar_ctrl = new VScrollBarLB ();
  1148. vscrollbar_ctrl.Minimum = 0;
  1149. vscrollbar_ctrl.SmallChange = 1;
  1150. vscrollbar_ctrl.LargeChange = 1;
  1151. vscrollbar_ctrl.Maximum = 0;
  1152. vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
  1153. vscrollbar_ctrl.Height = height - ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle) -
  1154. ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
  1155. vscrollbar_ctrl.Location = new Point (width - vscrollbar_ctrl.Width - ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle),
  1156. ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle));
  1157. vscrollbar_ctrl.Maximum = owner.Items.Count - owner.MaxDropDownItems;
  1158. Controls.Add (vscrollbar_ctrl);
  1159. }
  1160. Size = new Size (width, height);
  1161. textarea_drawable = ClientRectangle;
  1162. textarea_drawable.Width = width;
  1163. textarea_drawable.Height = height;
  1164. // Exclude decorations
  1165. textarea_drawable.X += ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
  1166. textarea_drawable.Y += ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
  1167. textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
  1168. textarea_drawable.Width -= ThemeEngine.Current.DrawComboListBoxDecorationLeft (owner.DropDownStyle);
  1169. textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationBottom (owner.DropDownStyle);
  1170. textarea_drawable.Height -= ThemeEngine.Current.DrawComboListBoxDecorationTop (owner.DropDownStyle);
  1171. if (vscrollbar_ctrl != null)
  1172. textarea_drawable.Width -= vscrollbar_ctrl.Width;
  1173. last_item = LastVisibleItem ();
  1174. page_size = textarea_drawable.Height / (item_height - 2);
  1175. }
  1176. private void Draw (Rectangle clip)
  1177. {
  1178. DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
  1179. (owner.BackColor), ClientRectangle);
  1180. if (owner.Items.Count > 0) {
  1181. Rectangle item_rect;
  1182. DrawItemState state = DrawItemState.None;
  1183. for (int i = top_item; i <= last_item; i++) {
  1184. item_rect = GetItemDisplayRectangle (i, top_item);
  1185. if (clip.IntersectsWith (item_rect) == false)
  1186. continue;
  1187. /* Draw item */
  1188. state = DrawItemState.None;
  1189. if (i == highlighted_item) {
  1190. state |= DrawItemState.Selected;
  1191. if (owner.DropDownStyle == ComboBoxStyle.DropDownList) {
  1192. state |= DrawItemState.Focus;
  1193. }
  1194. }
  1195. owner.OnDrawItem (new DrawItemEventArgs (DeviceContext, owner.Font, item_rect,
  1196. i, state, owner.ForeColor, owner.BackColor));
  1197. }
  1198. }
  1199. ThemeEngine.Current.DrawComboListBoxDecorations (DeviceContext, owner, ClientRectangle);
  1200. }
  1201. private Rectangle GetItemDisplayRectangle (int index, int first_displayble)
  1202. {
  1203. if (index < 0 || index >= owner.Items.Count)
  1204. throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
  1205. Rectangle item_rect = new Rectangle ();
  1206. int height = owner.GetItemHeight (index);
  1207. item_rect.X = ThemeEngine.Current.DrawComboListBoxDecorationRight (owner.DropDownStyle);
  1208. item_rect.Width = textarea_drawable.Width;
  1209. item_rect.Y = 2 + ((height - 2) * (index - first_displayble));
  1210. item_rect.Height = height;
  1211. return item_rect;
  1212. }
  1213. public void HideWindow ()
  1214. {
  1215. if (owner.DropDownStyle == ComboBoxStyle.Simple)
  1216. return;
  1217. Capture = false;
  1218. Hide ();
  1219. owner.DropDownListBoxFinished ();
  1220. }
  1221. private int IndexFromPointDisplayRectangle (int x, int y)
  1222. {
  1223. for (int i = top_item; i <= last_item; i++) {
  1224. if (GetItemDisplayRectangle (i, top_item).Contains (x, y) == true)
  1225. return i;
  1226. }
  1227. return -1;
  1228. }
  1229. protected override bool IsInputKey (Keys keyData)
  1230. {
  1231. return owner.IsInputKey (keyData);
  1232. }
  1233. private int LastVisibleItem ()
  1234. {
  1235. Rectangle item_rect;
  1236. int top_y = textarea_drawable.Y + textarea_drawable.Height;
  1237. int i = 0;
  1238. for (i = top_item; i < owner.Items.Count; i++) {
  1239. item_rect = GetItemDisplayRectangle (i, top_item);
  1240. if (item_rect.Y + item_rect.Height > top_y) {
  1241. return i;
  1242. }
  1243. }
  1244. return i - 1;
  1245. }
  1246. private void NavigateItemVisually (ItemNavigation navigation)
  1247. {
  1248. int item = -1;
  1249. switch (navigation) {
  1250. case ItemNavigation.Next: {
  1251. if (highlighted_item + 1 < owner.Items.Count) {
  1252. if (highlighted_item + 1 > last_item) {
  1253. top_item++;
  1254. vscrollbar_ctrl.Value = top_item;
  1255. }
  1256. item = highlighted_item + 1;
  1257. }
  1258. break;
  1259. }
  1260. case ItemNavigation.Previous: {
  1261. if (highlighted_item > 0) {
  1262. if (highlighted_item - 1 < top_item) {
  1263. top_item--;
  1264. vscrollbar_ctrl.Value = top_item;
  1265. }
  1266. item = highlighted_item - 1;
  1267. }
  1268. break;
  1269. }
  1270. case ItemNavigation.NextPage: {
  1271. if (highlighted_item + page_size - 1 >= owner.Items.Count) {
  1272. top_item = owner.Items.Count - page_size;
  1273. vscrollbar_ctrl.Value = top_item;
  1274. item = owner.Items.Count - 1;
  1275. }
  1276. else {
  1277. if (highlighted_item + page_size - 1 > last_item) {
  1278. top_item = highlighted_item;
  1279. vscrollbar_ctrl.Value = highlighted_item;
  1280. }
  1281. item = highlighted_item + page_size - 1;
  1282. }
  1283. break;
  1284. }
  1285. case ItemNavigation.PreviousPage: {
  1286. /* Go to the first item*/
  1287. if (highlighted_item - (page_size - 1) <= 0) {
  1288. top_item = 0;
  1289. vscrollbar_ctrl.Value = top_item;
  1290. item = 0;
  1291. }
  1292. else { /* One page back */
  1293. if (highlighted_item - (page_size - 1) < top_item) {
  1294. top_item = highlighted_item - (page_size - 1);
  1295. vscrollbar_ctrl.Value = top_item;
  1296. }
  1297. item = highlighted_item - (page_size - 1);
  1298. }
  1299. break;
  1300. }
  1301. default:
  1302. break;
  1303. }
  1304. if (item != -1) {
  1305. SetHighLightedItem (item);
  1306. owner.OnSelectionChangeCommitted (new EventArgs ());
  1307. if (owner.DropDownStyle == ComboBoxStyle.Simple) {
  1308. owner.SetControlText (owner.Items[item].ToString ());
  1309. }
  1310. }
  1311. }
  1312. private void OnKeyDownPUW (object sender, KeyEventArgs e)
  1313. {
  1314. switch (e.KeyCode) {
  1315. case Keys.Up:
  1316. NavigateItemVisually (ItemNavigation.Previous);
  1317. break;
  1318. case Keys.Down:
  1319. NavigateItemVisually (ItemNavigation.Next);
  1320. break;
  1321. case Keys.PageUp:
  1322. NavigateItemVisually (ItemNavigation.PreviousPage);
  1323. break;
  1324. case Keys.PageDown:
  1325. NavigateItemVisually (ItemNavigation.NextPage);
  1326. break;
  1327. default:
  1328. break;
  1329. }
  1330. }
  1331. public void SetHighLightedItem (int index)
  1332. {
  1333. Rectangle invalidate;
  1334. if (highlighted_item == index)
  1335. return;
  1336. /* Previous item */
  1337. if (highlighted_item != -1) {
  1338. invalidate = GetItemDisplayRectangle (highlighted_item, top_item);
  1339. if (ClientRectangle.Contains (invalidate))
  1340. Invalidate (invalidate);
  1341. }
  1342. highlighted_item = index;
  1343. /* Current item */
  1344. invalidate = GetItemDisplayRectangle (highlighted_item, top_item);
  1345. if (ClientRectangle.Contains (invalidate))
  1346. Invalidate (invalidate);
  1347. }
  1348. public void SetTopItem (int item)
  1349. {
  1350. top_item = item;
  1351. UpdateLastVisibleItem ();
  1352. Refresh ();
  1353. }
  1354. private void OnMouseDownPUW (object sender, MouseEventArgs e)
  1355. {
  1356. Rectangle scrollbar_screenrect;
  1357. Point mouse_screen, scrollbar_screen;
  1358. mouse_screen = PointToScreen (new Point (e.X, e.Y));
  1359. /* Click on an element ? */
  1360. int index = IndexFromPointDisplayRectangle (e.X, e.Y);
  1361. if (index != -1) {
  1362. owner.SelectedIndex = index;
  1363. SetHighLightedItem (index);
  1364. owner.OnSelectionChangeCommitted (new EventArgs ());
  1365. HideWindow ();
  1366. return;
  1367. }
  1368. if (owner.DropDownStyle == ComboBoxStyle.Simple)
  1369. return;
  1370. /* Reroute event to scrollbar */
  1371. if (vscrollbar_ctrl != null) {
  1372. scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
  1373. scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
  1374. scrollbar_screenrect.X = scrollbar_screen.X;
  1375. scrollbar_screenrect.Y = scrollbar_screen.Y;
  1376. if (scrollbar_screenrect.Contains (mouse_screen)){
  1377. Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
  1378. vscrollbar_ctrl.FireMouseDown (new MouseEventArgs (e.Button, e.Clicks,
  1379. pnt_client.X, pnt_client.Y, e.Delta));
  1380. } else { /* Click in a non-client area*/
  1381. HideWindow ();
  1382. }
  1383. } else { /* Click in a non-client area*/
  1384. HideWindow ();
  1385. }
  1386. }
  1387. private void OnMouseMovePUW (object sender, MouseEventArgs e)
  1388. {
  1389. if (owner.DropDownStyle == ComboBoxStyle.Simple)
  1390. return;
  1391. int index = IndexFromPointDisplayRectangle (e.X, e.Y);
  1392. if (index != -1) {
  1393. SetHighLightedItem (index);
  1394. return;
  1395. }
  1396. if (owner.DropDownStyle == ComboBoxStyle.Simple)
  1397. return;
  1398. /* Reroute event to scrollbar */
  1399. if (vscrollbar_ctrl != null) {
  1400. Rectangle scrollbar_screenrect;
  1401. Point mouse_screen, scrollbar_screen;
  1402. mouse_screen = PointToScreen (new Point (e.X, e.Y));
  1403. scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
  1404. scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
  1405. scrollbar_screenrect.X = scrollbar_screen.X;
  1406. scrollbar_screenrect.Y = scrollbar_screen.Y;
  1407. if (scrollbar_screenrect.Contains (mouse_screen)){
  1408. Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
  1409. vscrollbar_ctrl.FireMouseMove (new MouseEventArgs (e.Button, e.Clicks,
  1410. pnt_client.X, pnt_client.Y, e.Delta));
  1411. }
  1412. }
  1413. }
  1414. private void OnMouseUpPUW (object sender, MouseEventArgs e)
  1415. {
  1416. if (owner.DropDownStyle == ComboBoxStyle.Simple)
  1417. return;
  1418. /* Reroute event to scrollbar */
  1419. Rectangle scrollbar_screenrect;
  1420. Point mouse_screen, scrollbar_screen;
  1421. mouse_screen = PointToScreen (new Point (e.X, e.Y));
  1422. if (vscrollbar_ctrl != null) {
  1423. scrollbar_screenrect = vscrollbar_ctrl.ClientRectangle;
  1424. scrollbar_screen = PointToScreen (vscrollbar_ctrl.Location);
  1425. scrollbar_screenrect.X = scrollbar_screen.X;
  1426. scrollbar_screenrect.Y = scrollbar_screen.Y;
  1427. if (scrollbar_screenrect.Contains (mouse_screen)){
  1428. Point pnt_client = vscrollbar_ctrl.PointToClient (mouse_screen);
  1429. vscrollbar_ctrl.FireMouseUp (new MouseEventArgs (e.Button, e.Clicks,
  1430. pnt_client.X, pnt_client.Y, e.Delta));
  1431. }
  1432. }
  1433. }
  1434. private void OnPaintPUW (Object o, PaintEventArgs pevent)
  1435. {
  1436. if (Width <= 0 || Height <= 0 || Visible == false)
  1437. return;
  1438. Draw (pevent.ClipRectangle);
  1439. pevent.Graphics.DrawImage (ImageBuffer, pevent.ClipRectangle, pevent.ClipRectangle, GraphicsUnit.Pixel);
  1440. }
  1441. public bool ShowWindow ()
  1442. {
  1443. if (owner.DropDownStyle != ComboBoxStyle.Simple && owner.Items.Count == 0)
  1444. return false;
  1445. CalcListBoxArea ();
  1446. Show ();
  1447. if (owner.DropDownStyle != ComboBoxStyle.Simple) {
  1448. Capture = true;
  1449. }
  1450. Refresh ();
  1451. if (owner.DropDown != null) {
  1452. owner.DropDown (owner, EventArgs.Empty);
  1453. }
  1454. return true;
  1455. }
  1456. public void UpdateLastVisibleItem ()
  1457. {
  1458. last_item = LastVisibleItem ();
  1459. }
  1460. // Value Changed
  1461. private void VerticalScrollEvent (object sender, EventArgs e)
  1462. {
  1463. top_item = vscrollbar_ctrl.Value;
  1464. UpdateLastVisibleItem ();
  1465. Refresh ();
  1466. }
  1467. #endregion Private Methods
  1468. }
  1469. }
  1470. }