- Main Page
- Packages
- Classes
- Files

- File List
- File Members

# D:/guillaume/guillara/3D/DXGfx/DXCommon/dxmutgui.cs

Go to the documentation of this file.

    00001 //--------------------------------------------------------------------------------------
    00002 // File: DXMUTGui.cs
    00003 //
    00004 // DirectX SDK Managed Direct3D GUI Sample Code
    00005 //
    00006 // Copyright (c) Microsoft Corporation. All rights reserved.
    00007 //--------------------------------------------------------------------------------------
    00008 using System;
    00009 using System.Collections;
    00010 using Microsoft.DirectX;
    00011 using Microsoft.DirectX.Direct3D;
    00012
    00013 namespace Microsoft.Samples.DirectX.UtilityToolkit
    00014 {
    00018     public enum ControlType
    00019     {
    00020         StaticText,
    00021         Button,
    00022         CheckBox,
    00023         RadioButton,
    00024         ComboBox,
    00025         Slider,
    00026         ListBox,
    00027         EditBox,
    00028         Scrollbar,
    00029     }
    00030
    00034     public enum ControlState
    00035     {
    00036         Normal,
    00037         Disabled,
    00038         Hidden,
    00039         Focus,
    00040         MouseOver,
    00041         Pressed,
    00042         LastState // Should always be last
    00043     }
    00044
    00048     public struct BlendColor
    00049     {
    00050         public ColorValue[] States; // Modulate colors for all possible control states
    00051         public ColorValue Current; // Current color
    00052
    00054         public void Initialize(ColorValue defaultColor, ColorValue disabledColor, ColorValue hiddenColor)
    00055         {
    00056             // Create the array
    00057             States = new ColorValue[(int)ControlState.LastState];
    00058             for(int i = 0; i < States.Length; i++)
    00059             {
    00060                 States[i] = defaultColor;
    00061             }
    00062
    00063             // Store the data
    00064             States[(int)ControlState.Disabled] = disabledColor;
    00065             States[(int)ControlState.Hidden] = hiddenColor;
    00066             Current = hiddenColor;
    00067         }
    00069         public void Initialize(ColorValue defaultColor) { Initialize( defaultColor, new ColorValue(0.5f, 0.5f, 0.5f, 0.75f),new ColorValue()); }
    00070
    00072         public void Blend(ControlState state, float elapsedTime, float rate)
    00073         {
    00074             if ((States == null) || (States.Length == 0) )
    00075                 return; // Nothing to do
    00076
    00077             ColorValue destColor = States[(int)state];
    00078             Current = ColorOperator.Lerp(Current, destColor, 1.0f - (float)Math.Pow(rate, 30 * elapsedTime) );
    00079         }
    00081         public void Blend(ControlState state, float elapsedTime) { Blend(state, elapsedTime, 0.7f); }
    00082     }
    00083
    00087     public struct ElementHolder
    00088     {
    00089         public ControlType ControlType;
    00090         public uint ElementIndex;
    00091         public Element Element;
    00092     }
    00093
    00097     public class Element : ICloneable
    00098     {
    00099         #region Magic Numbers
    00100         #endregion
    00101
    00102         #region Instance Data
    00103         public uint TextureIndex; // Index of the texture for this Element
    00104         public uint FontIndex; // Index of the font for this Element
    00105         public DrawTextFormat textFormat; // The Format argument to draw text
    00106
    00107         public System.Drawing.Rectangle textureRect; // Bounding rectangle of this element on the composite texture
    00108
    00109         public BlendColor TextureColor;
    00110         public BlendColor FontColor;
    00111         #endregion
    00112
    00114         public void SetTexture(uint tex, System.Drawing.Rectangle texRect, ColorValue defaultTextureColor)
    00115         {
    00116             // Store data
    00117             TextureIndex = tex;
    00118             textureRect = texRect;
    00119             TextureColor.Initialize(defaultTextureColor);
    00120         }
    00122         public void SetTexture(uint tex, System.Drawing.Rectangle texRect) { SetTexture(tex, texRect, Dialog.WhiteColorValue); }
    00124         public void SetFont(uint font, ColorValue defaultFontColor, DrawTextFormat format)
    00125         {
    00126             // Store data
    00127             FontIndex = font;
    00128             textFormat = format;
    00129             FontColor.Initialize(defaultFontColor);
    00130         }
    00132         public void SetFont(uint font){ SetFont(font, Dialog.WhiteColorValue, DrawTextFormat.Center | DrawTextFormat.VerticalCenter ); }
    00136         public void Refresh()
    00137         {
    00138             if (TextureColor.States != null)
    00139                 TextureColor.Current = TextureColor.States[(int)ControlState.Hidden];
    00140             if (FontColor.States != null)
    00141                 FontColor.Current = FontColor.States[(int)ControlState.Hidden];
    00142         }
    00143
    00144         #region ICloneable Members
    00146         public Element Clone()
    00147         {
    00148             Element e = new Element();
    00149             e.TextureIndex = this.TextureIndex;
    00150             e.FontIndex = this.FontIndex;
    00151             e.textFormat = this.textFormat;
    00152             e.textureRect = this.textureRect;
    00153             e.TextureColor = this.TextureColor;
    00154             e.FontColor = this.FontColor;
    00155
    00156             return e;
    00157         }
    00159         object ICloneable.Clone() { throw new NotSupportedException("Use the strongly typed clone.");}
    00160
    00161         #endregion
    00162     }
    00163
    00164
    00165     #region Dialog Resource Manager
    00169     public class TextureNode
    00170     {
    00171         public string Filename;
    00172         public Texture Texture;
    00173         public uint Width;
    00174         public uint Height;
    00175     }
    00176
    00180     public class FontNode
    00181     {
    00182         public string FaceName;
    00183         public Font Font;
    00184         public uint Height;
    00185         public FontWeight Weight;
    00186     }
    00187
    00191     public sealed class DialogResourceManager
    00192     {
    00193         private StateBlock dialogStateBlock;  // Stateblock shared amongst all dialogs
    00194         private Sprite dialogSprite; // Sprite used for drawing
    00195         public StateBlock StateBlock { get { return dialogStateBlock; } }
    00196         public Sprite Sprite { get { return dialogSprite; } }
    00197         private Device device; // Device
    00198
    00199         // Lists of textures/fonts
    00200         private ArrayList textureCache = new ArrayList();
    00201         private ArrayList fontCache = new ArrayList();
    00202
    00203         #region Creation
    00205         private DialogResourceManager()  {
    00206             device = null;
    00207             dialogSprite = null;
    00208             dialogStateBlock = null;
    00209         }
    00210
    00211         private static DialogResourceManager localObject = null;
    00212         public static DialogResourceManager GetGlobalInstance()
    00213         {
    00214             if (localObject == null)
    00215                 localObject = new DialogResourceManager();
    00216
    00217             return localObject;
    00218         }
    00219         #endregion
    00220
    00222         public FontNode GetFontNode(int index) { return fontCache[index] as FontNode; }
    00224         public TextureNode GetTextureNode(int index) { return textureCache[index] as TextureNode; }
    00226         public Device Device { get { return device; } }
    00227
    00231         public int AddFont(string faceName, uint height, FontWeight weight)
    00232         {
    00233             // See if this font exists
    00234             for(int i = 0; i < fontCache.Count; i++)
    00235             {
    00236                 FontNode fn = fontCache[i] as FontNode;
    00237                 if ( (string.Compare(fn.FaceName, faceName, true) == 0) &&
    00238                     fn.Height == height &&
    00239                     fn.Weight == weight)
    00240                 {
    00241                     // Found it
    00242                     return i;
    00243                 }
    00244             }
    00245
    00246             // Doesn't exist, add a new one and try to create it
    00247             FontNode newNode = new FontNode();
    00248             newNode.FaceName = faceName;
    00249             newNode.Height = height;
    00250             newNode.Weight = weight;
    00251             fontCache.Add(newNode);
    00252
    00253             int fontIndex = fontCache.Count-1;
    00254             // If a device is available, try to create immediately
    00255             if (device != null)
    00256                 CreateFont(fontIndex);
    00257
    00258             return fontIndex;
    00259         }
    00263         public int AddTexture(string filename)
    00264         {
    00265             // See if this font exists
    00266             for(int i = 0; i < textureCache.Count; i++)
    00267             {
    00268                 TextureNode tn = textureCache[i] as TextureNode;
    00269                 if (string.Compare(tn.Filename, filename, true) == 0)
    00270                 {
    00271                     // Found it
    00272                     return i;
    00273                 }
    00274             }
    00275             // Doesn't exist, add a new one and try to create it
    00276             TextureNode newNode = new TextureNode();
    00277             newNode.Filename = filename;
    00278             textureCache.Add(newNode);
    00279
    00280             int texIndex = textureCache.Count-1;
    00281
    00282             // If a device is available, try to create immediately
    00283             if (device != null)
    00284                 CreateTexture(texIndex);
    00285
    00286             return texIndex;
    00287
    00288         }
    00289
    00293         public void CreateFont(int font)
    00294         {
    00295             // Get the font node here
    00296             FontNode fn = GetFontNode(font);
    00297             if (fn.Font != null)
    00298                 fn.Font.Dispose(); // Get rid of this
    00299
    00300             // Create the new font
    00301             fn.Font = new Font(device, (int)fn.Height, 0, fn.Weight, 1, false, CharacterSet.Default,
    00302                 Precision.Default, FontQuality.Default, PitchAndFamily.DefaultPitch | PitchAndFamily.FamilyDoNotCare,
    00303                 fn.FaceName);
    00304         }
    00305
    00309         public void CreateTexture(int tex)
    00310         {
    00311             // Get the texture node here
    00312             TextureNode tn = GetTextureNode(tex);
    00313
    00314             // Make sure there's a texture to create
    00315             if ((tn.Filename == null) || (tn.Filename.Length == 0))
    00316                 return;
    00317
    00318             // Find the texture
    00319             string path = Utility.FindMediaFile(tn.Filename);
    00320
    00321             // Create the new texture
    00322             ImageInformation info = new ImageInformation();
    00323             tn.Texture = TextureLoader.FromFile(device, path, D3DX.Default, D3DX.Default, D3DX.Default, Usage.None,
    00324                 Format.Unknown, Pool.Managed, (Filter)D3DX.Default, (Filter)D3DX.Default, 0, ref info);
    00325
    00326             // Store dimensions
    00327             tn.Width = (uint)info.Width;
    00328             tn.Height = (uint)info.Height;
    00329
    00330         }
    00331
    00332         #region Device event callbacks
    00336         public void OnCreateDevice(Device d)
    00337         {
    00338             // Store device
    00339             device = d;
    00340
    00341             // create fonts and textures
    00342             for (int i = 0; i < fontCache.Count; i++)
    00343                 CreateFont(i);
    00344
    00345             for (int i = 0; i < textureCache.Count; i++)
    00346                 CreateTexture(i);
    00347
    00348             dialogSprite = new Sprite(d); // Create the sprite
    00349         }
    00353         public void OnResetDevice(Device device)
    00354         {
    00355             foreach(FontNode fn in fontCache)
    00356                 fn.Font.OnResetDevice();
    00357
    00358             if (dialogSprite != null)
    00359                 dialogSprite.OnResetDevice();
    00360
    00361             // Create new state block
    00362             dialogStateBlock = new StateBlock(device, StateBlockType.All);
    00363         }
    00364
    00368         public void OnLostDevice()
    00369         {
    00370             foreach(FontNode fn in fontCache)
    00371             {
    00372                 if ( (fn.Font != null) && (!fn.Font.Disposed) )
    00373                     fn.Font.OnLostDevice();
    00374             }
    00375
    00376             if (dialogSprite != null)
    00377                 dialogSprite.OnLostDevice();
    00378
    00379             if (dialogStateBlock != null)
    00380             {
    00381                 dialogStateBlock.Dispose();
    00382                 dialogStateBlock = null;
    00383             }
    00384         }
    00385
    00389         public void OnDestroyDevice()
    00390         {
    00391             foreach(FontNode fn in fontCache)
    00392             {
    00393                 if (fn.Font != null)
    00394                     fn.Font.Dispose();
    00395             }
    00396
    00397             foreach(TextureNode tn in textureCache)
    00398             {
    00399                 if (tn.Texture != null)
    00400                     tn.Texture.Dispose();
    00401             }
    00402
    00403             if (dialogSprite != null)
    00404             {
    00405                 dialogSprite.Dispose();
    00406                 dialogSprite = null;
    00407             }
    00408
    00409             if (dialogStateBlock != null)
    00410             {
    00411                 dialogStateBlock.Dispose();
    00412                 dialogStateBlock = null;
    00413             }
    00414         }
    00415
    00416         #endregion
    00417     }
    00418
    00419     #endregion
    00420
    00425     public class Dialog
    00426     {
    00427         #region Static Data
    00428         public const int WheelDelta = 120;
    00429         public static readonly ColorValue WhiteColorValue = new ColorValue(1.0f, 1.0f, 1.0f, 1.0f);
    00430         public static readonly ColorValue TransparentWhite = new ColorValue(1.0f, 1.0f, 1.0f, 0.0f);
    00431         public static readonly ColorValue BlackColorValue = new ColorValue(0.0f, 0.0f, 0.0f, 1.0f);
    00432         private static Control controlFocus = null; // The control which has focus
    00433         private static Control controlMouseOver = null; // The control which is hovered over
    00434         private static Control controlMouseDown = null; // The control which the mouse was pressed on
    00435
    00436         private static double timeRefresh = 0.0;
    00438         public static void SetRefreshTime(float time) { timeRefresh = time; }
    00439         #endregion
    00440
    00441         #region Instance Data
    00442         // Sample framework
    00443         private Framework parent = null;
    00444         public Framework SampleFramework { get { return parent; } }
    00445
    00446         // Vertex information
    00447         private CustomVertex.TransformedColoredTextured[] vertices;
    00448
    00449         // Timing
    00450         private double timeLastRefresh;
    00451
    00452         // Control/Elements
    00453         private ArrayList controlList = new ArrayList();
    00454         private ArrayList defaultElementList = new ArrayList();
    00455
    00456         // Captions
    00457         private bool hasCaption;
    00458         private string caption;
    00459         private int captionHeight;
    00460         private Element captionElement;
    00461         private bool isDialogMinimized;
    00462
    00463         // Dialog information
    00464         private int dialogX, dialogY, width, height;
    00465         // Colors
    00466         private ColorValue topLeftColor, topRightColor, bottomLeftColor, bottomRightColor;
    00467
    00468         // Fonts/Textures
    00469         private ArrayList textureList = new ArrayList(); // Index into texture cache
    00470         private ArrayList fontList = new ArrayList(); // Index into font cache
    00471
    00472         // Dialogs
    00473         private Dialog nextDialog;
    00474         private Dialog prevDialog;
    00475
    00476         // User Input control
    00477         private bool usingNonUserEvents;
    00478         private bool usingKeyboardInput;
    00479         private bool usingMouseInput;
    00480         #endregion
    00481
    00482         #region Simple Properties/Methods
    00484         public bool IsUsingNonUserEvents { get { return usingNonUserEvents; } set { usingNonUserEvents = value; } }
    00486         public bool IsUsingKeyboardInput { get { return usingKeyboardInput; } set { usingKeyboardInput = value; } }
    00488         public bool IsUsingMouseInput { get { return usingMouseInput; } set { usingMouseInput = value; } }
    00490         public bool IsMinimized { get { return isDialogMinimized; } set { isDialogMinimized = value; } }
    00492         public void SetLocation(int x, int y) { dialogX = x; dialogY = y; UpdateVertices(); }
    00494         public System.Drawing.Point Location {
    00495             get {return new System.Drawing.Point(dialogX, dialogY); }
    00496             set { dialogX = value.X; dialogY = value.Y; UpdateVertices(); }
    00497         }
    00498
    00500         public void SetSize(int w, int h) { width = w; height = h; UpdateVertices();}
    00502         public int Width { get { return width; } set { width = value; } }
    00504         public int Height { get { return height; } set { height = value; } }
    00506         public void SetCaptionText(string text) { caption = text; }
    00508         public int CaptionHeight { get { return captionHeight; } set { captionHeight = value; } }
    00510         public void SetCaptionEnabled(bool isEnabled) { hasCaption = isEnabled; }
    00512         public void SetBackgroundColors(ColorValue topLeft, ColorValue topRight, ColorValue bottomLeft, ColorValue bottomRight)
    00513         {
    00514             topLeftColor = topLeft; topRightColor = topRight; bottomLeftColor = bottomLeft; bottomRightColor = bottomRight;
    00515             UpdateVertices();
    00516         }
    00518         public void SetBackgroundColors(ColorValue allCorners) { SetBackgroundColors(allCorners, allCorners, allCorners, allCorners); }
    00519
    00520         #endregion
    00521
    00525         public Dialog(Framework sample)
    00526         {
    00527             parent = sample; // store this for later use
    00528             // Initialize to default state
    00529             dialogX = 0; dialogY = 0; width = 0; height = 0;
    00530             hasCaption = false; isDialogMinimized = false;
    00531             caption = string.Empty;
    00532             captionHeight = 18;
    00533
    00534             topLeftColor = topRightColor = bottomLeftColor = bottomRightColor = new ColorValue();
    00535
    00536             timeLastRefresh = 0.0f;
    00537
    00538             nextDialog = this; // Only one dialog
    00539             prevDialog = this;  // Only one dialog
    00540
    00541             usingNonUserEvents = false;
    00542             usingKeyboardInput = false;
    00543             usingMouseInput = true;
    00544
    00545             InitializeDefaultElements();
    00546         }
    00547
    00551         private void InitializeDefaultElements()
    00552         {
    00553             SetTexture(0, "UI\\DXUTControls.dds");
    00554             SetFont(0, "Arial", 14, FontWeight.Normal);
    00555
    00556             //-------------------------------------
    00557             // Element for the caption
    00558             //-------------------------------------
    00559             captionElement = new Element();
    00560             captionElement.SetFont(0, WhiteColorValue, DrawTextFormat.Left | DrawTextFormat.VerticalCenter);
    00561             captionElement.SetTexture(0, System.Drawing.Rectangle.FromLTRB(17, 269, 241, 287));
    00562             captionElement.TextureColor.States[(int)ControlState.Normal] = WhiteColorValue;
    00563             captionElement.FontColor.States[(int)ControlState.Normal] = WhiteColorValue;
    00564             // Pre-blend as we don't need to transition the state
    00565             captionElement.TextureColor.Blend(ControlState.Normal, 10.0f);
    00566             captionElement.FontColor.Blend(ControlState.Normal, 10.0f);
    00567
    00568             Element e = new Element();
    00569
    00570             //-------------------------------------
    00571             // StaticText
    00572             //-------------------------------------
    00573             e.SetFont(0);
    00574             e.FontColor.States[(int)ControlState.Disabled] = new ColorValue(0.75f, 0.75f, 0.75f, 0.75f);
    00575             // Assign the element
    00576             SetDefaultElement(ControlType.StaticText, StaticText.TextElement, e);
    00577
    00578             //-------------------------------------
    00579             // Button - Button
    00580             //-------------------------------------
    00581             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(0, 0, 136, 54));
    00582             e.SetFont(0);
    00583             e.TextureColor.States[(int)ControlState.Normal] = new ColorValue(1.0f, 1.0f, 1.0f, 0.55f);
    00584             e.TextureColor.States[(int)ControlState.Pressed] = new ColorValue(1.0f, 1.0f, 1.0f, 0.85f);
    00585             e.FontColor.States[(int)ControlState.MouseOver] = BlackColorValue;
    00586             // Assign the element
    00587             SetDefaultElement(ControlType.Button, Button.ButtonLayer, e);
    00588
    00589             //-------------------------------------
    00590             // Button - Fill Layer
    00591             //-------------------------------------
    00592             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(136, 0, 252, 54), TransparentWhite);
    00593             e.TextureColor.States[(int)ControlState.MouseOver] = new ColorValue(1.0f, 1.0f, 1.0f, 0.6f);
    00594             e.TextureColor.States[(int)ControlState.Pressed] = new ColorValue(0,0,0, 0.25f);
    00595             e.TextureColor.States[(int)ControlState.Focus] = new ColorValue(1.0f, 1.0f, 1.0f, 0.05f);
    00596             // Assign the element
    00597             SetDefaultElement(ControlType.Button, Button.FillLayer, e);
    00598
    00599
    00600             //-------------------------------------
    00601             // CheckBox - Box
    00602             //-------------------------------------
    00603             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(0, 54, 27, 81));
    00604             e.SetFont(0, WhiteColorValue, DrawTextFormat.Left | DrawTextFormat.VerticalCenter);
    00605             e.FontColor.States[(int)ControlState.Disabled] = new ColorValue(0.8f, 0.8f, 0.8f, 0.8f);
    00606             e.TextureColor.States[(int)ControlState.Normal] = new ColorValue(1.0f, 1.0f, 1.0f, 0.55f);
    00607             e.TextureColor.States[(int)ControlState.Focus] = new ColorValue(1.0f, 1.0f, 1.0f, 0.8f);
    00608             e.TextureColor.States[(int)ControlState.Pressed] = WhiteColorValue;
    00609             // Assign the element
    00610             SetDefaultElement(ControlType.CheckBox, Checkbox.BoxLayer, e);
    00611
    00612             //-------------------------------------
    00613             // CheckBox - Check
    00614             //-------------------------------------
    00615             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(27, 54, 54, 81));
    00616             // Assign the element
    00617             SetDefaultElement(ControlType.CheckBox, Checkbox.CheckLayer, e);
    00618
    00619             //-------------------------------------
    00620             // RadioButton - Box
    00621             //-------------------------------------
    00622             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(54, 54, 81, 81));
    00623             e.SetFont(0, WhiteColorValue, DrawTextFormat.Left | DrawTextFormat.VerticalCenter);
    00624             e.FontColor.States[(int)ControlState.Disabled] = new ColorValue(0.8f, 0.8f, 0.8f, 0.8f);
    00625             e.TextureColor.States[(int)ControlState.Normal] = new ColorValue(1.0f, 1.0f, 1.0f, 0.55f);
    00626             e.TextureColor.States[(int)ControlState.Focus] = new ColorValue(1.0f, 1.0f, 1.0f, 0.8f);
    00627             e.TextureColor.States[(int)ControlState.Pressed] = WhiteColorValue;
    00628             // Assign the element
    00629             SetDefaultElement(ControlType.RadioButton, RadioButton.BoxLayer, e);
    00630
    00631             //-------------------------------------
    00632             // RadioButton - Check
    00633             //-------------------------------------
    00634             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(81, 54, 108, 81));
    00635             // Assign the element
    00636             SetDefaultElement(ControlType.RadioButton, RadioButton.CheckLayer, e);
    00637
    00638             //-------------------------------------
    00639             // ComboBox - Main
    00640             //-------------------------------------
    00641             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(7, 81, 247, 123));
    00642             e.SetFont(0);
    00643             e.TextureColor.States[(int)ControlState.Normal] = new ColorValue(0.8f, 0.8f, 0.8f, 0.55f);
    00644             e.TextureColor.States[(int)ControlState.Focus] = new ColorValue(0.95f, 0.95f, 0.95f, 0.6f);
    00645             e.TextureColor.States[(int)ControlState.Disabled] = new ColorValue(0.8f, 0.8f, 0.8f, 0.25f);
    00646             e.FontColor.States[(int)ControlState.MouseOver] = new ColorValue(0,0,0,1.0f);
    00647             e.FontColor.States[(int)ControlState.Pressed] = new ColorValue(0,0,0,1.0f);
    00648             e.FontColor.States[(int)ControlState.Disabled] = new ColorValue(0.8f, 0.8f, 0.8f, 0.8f);
    00649             // Assign the element
    00650             SetDefaultElement(ControlType.ComboBox, ComboBox.MainLayer, e);
    00651
    00652             //-------------------------------------
    00653             // ComboBox - Button
    00654             //-------------------------------------
    00655             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(98, 189, 151, 238));
    00656             e.TextureColor.States[(int)ControlState.Normal] = new ColorValue(1.0f, 1.0f, 1.0f, 0.55f);
    00657             e.TextureColor.States[(int)ControlState.Pressed] = new ColorValue(0.55f, 0.55f, 0.55f, 1.0f);
    00658             e.TextureColor.States[(int)ControlState.Focus] = new ColorValue(1.0f, 1.0f, 1.0f, 0.75f);
    00659             e.TextureColor.States[(int)ControlState.Disabled] = new ColorValue(1.0f, 1.0f, 1.0f, 0.25f);
    00660             // Assign the element
    00661             SetDefaultElement(ControlType.ComboBox, ComboBox.ComboButtonLayer, e);
    00662
    00663             //-------------------------------------
    00664             // ComboBox - Dropdown
    00665             //-------------------------------------
    00666             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(13, 123, 241, 160));
    00667             e.SetFont(0, BlackColorValue, DrawTextFormat.Left | DrawTextFormat.Top);
    00668             // Assign the element
    00669             SetDefaultElement(ControlType.ComboBox, ComboBox.DropdownLayer, e);
    00670
    00671             //-------------------------------------
    00672             // ComboBox - Selection
    00673             //-------------------------------------
    00674             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(12, 163, 239, 183));
    00675             e.SetFont(0, WhiteColorValue, DrawTextFormat.Left | DrawTextFormat.Top);
    00676             // Assign the element
    00677             SetDefaultElement(ControlType.ComboBox, ComboBox.SelectionLayer, e);
    00678
    00679             //-------------------------------------
    00680             // Slider - Track
    00681             //-------------------------------------
    00682             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(1, 187, 93, 228));
    00683             e.TextureColor.States[(int)ControlState.Normal] = new ColorValue(1.0f, 1.0f, 1.0f, 0.55f);
    00684             e.TextureColor.States[(int)ControlState.Focus] = new ColorValue(1.0f, 1.0f, 1.0f, 0.75f);
    00685             e.TextureColor.States[(int)ControlState.Disabled] = new ColorValue(1.0f, 1.0f, 1.0f, 0.25f);
    00686             // Assign the element
    00687             SetDefaultElement(ControlType.Slider, Slider.TrackLayer, e);
    00688
    00689             //-------------------------------------
    00690             // Slider - Button
    00691             //-------------------------------------
    00692             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(151, 193, 192, 234));
    00693             // Assign the element
    00694             SetDefaultElement(ControlType.Slider, Slider.ButtonLayer, e);
    00695
    00696             //-------------------------------------
    00697             // Scrollbar - Track
    00698             //-------------------------------------
    00699             int scrollBarStartX = 196;
    00700             int scrollBarStartY = 191;
    00701             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(scrollBarStartX + 0, scrollBarStartY + 21, scrollBarStartX + 22, scrollBarStartY + 32));
    00702             // Assign the element
    00703             SetDefaultElement(ControlType.Scrollbar, ScrollBar.TrackLayer, e);
    00704
    00705             //-------------------------------------
    00706             // Scrollbar - Up Arrow
    00707             //-------------------------------------
    00708             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(scrollBarStartX + 0, scrollBarStartY + 1, scrollBarStartX + 22, scrollBarStartY + 21));
    00709             e.TextureColor.States[(int)ControlState.Disabled] = new ColorValue(0.8f, 0.8f, 0.8f, 1.0f);
    00710             // Assign the element
    00711             SetDefaultElement(ControlType.Scrollbar, ScrollBar.UpButtonLayer, e);
    00712
    00713             //-------------------------------------
    00714             // Scrollbar - Down Arrow
    00715             //-------------------------------------
    00716             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(scrollBarStartX + 0, scrollBarStartY + 32, scrollBarStartX + 22, scrollBarStartY + 53));
    00717             e.TextureColor.States[(int)ControlState.Disabled] = new ColorValue(0.8f, 0.8f, 0.8f, 1.0f);
    00718             // Assign the element
    00719             SetDefaultElement(ControlType.Scrollbar, ScrollBar.DownButtonLayer, e);
    00720
    00721             //-------------------------------------
    00722             // Scrollbar - Button
    00723             //-------------------------------------
    00724             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(220, 192, 238, 234));
    00725             // Assign the element
    00726             SetDefaultElement(ControlType.Scrollbar, ScrollBar.ThumbLayer, e);
    00727
    00728
    00729             //-------------------------------------
    00730             // EditBox
    00731             //-------------------------------------
    00732             // Element assignment:
    00733             //   0 - text area
    00734             //   1 - top left border
    00735             //   2 - top border
    00736             //   3 - top right border
    00737             //   4 - left border
    00738             //   5 - right border
    00739             //   6 - lower left border
    00740             //   7 - lower border
    00741             //   8 - lower right border
    00742             e.SetFont(0, BlackColorValue, DrawTextFormat.Left | DrawTextFormat.Top);
    00743
    00744             // Assign the styles
    00745             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(14, 90, 241, 113));
    00746             SetDefaultElement(ControlType.EditBox, EditBox.TextLayer, e);
    00747             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(8, 82, 14, 90));
    00748             SetDefaultElement(ControlType.EditBox, EditBox.TopLeftBorder, e);
    00749             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(14, 82, 241, 90));
    00750             SetDefaultElement(ControlType.EditBox, EditBox.TopBorder, e);
    00751             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(241, 82, 246, 90));
    00752             SetDefaultElement(ControlType.EditBox, EditBox.TopRightBorder, e);
    00753             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(8, 90, 14, 113));
    00754             SetDefaultElement(ControlType.EditBox, EditBox.LeftBorder, e);
    00755             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(241, 90, 246, 113));
    00756             SetDefaultElement(ControlType.EditBox, EditBox.RightBorder, e);
    00757             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(8, 113, 14, 121));
    00758             SetDefaultElement(ControlType.EditBox, EditBox.LowerLeftBorder, e);
    00759             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(14, 113, 241, 121));
    00760             SetDefaultElement(ControlType.EditBox, EditBox.LowerBorder, e);
    00761             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(241, 113, 246, 121));
    00762             SetDefaultElement(ControlType.EditBox, EditBox.LowerRightBorder, e);
    00763
    00764
    00765             //-------------------------------------
    00766             // Listbox - Main
    00767             //-------------------------------------
    00768             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(13, 123, 241, 160));
    00769             e.SetFont(0, BlackColorValue, DrawTextFormat.Left | DrawTextFormat.Top);
    00770             // Assign the element
    00771             SetDefaultElement(ControlType.ListBox, ListBox.MainLayer, e);
    00772
    00773             //-------------------------------------
    00774             // Listbox - Selection
    00775             //-------------------------------------
    00776             e.SetTexture(0, System.Drawing.Rectangle.FromLTRB(16, 166, 240, 183));
    00777             e.SetFont(0, WhiteColorValue, DrawTextFormat.Left | DrawTextFormat.Top);
    00778             // Assign the element
    00779             SetDefaultElement(ControlType.ListBox, ListBox.SelectionLayer, e);
    00780         }
    00781
    00783         public void RemoveAllControls()
    00784         {
    00785             controlList.Clear();
    00786             if ( (controlFocus != null) && (controlFocus.Parent == this) )
    00787                 controlFocus = null;
    00788
    00789             controlMouseOver = null;
    00790         }
    00791
    00793         public void ClearRadioButtonGroup(uint groupIndex)
    00794         {
    00795             // Find all radio buttons with the given group number
    00796             foreach(Control c in controlList)
    00797             {
    00798                 if (c.ControlType == ControlType.RadioButton)
    00799                 {
    00800                     RadioButton rb = c as RadioButton;
    00801                     // Clear the radio button checked setting
    00802                     if (rb.ButtonGroup == groupIndex)
    00803                         rb.SetChecked(false, false);
    00804                 }
    00805             }
    00806         }
    00807
    00809         public void ClearComboBox(int id)
    00810         {
    00811             ComboBox comboBox = GetComboBox(id);
    00812             if (comboBox == null)
    00813                 return;
    00814
    00815             comboBox.Clear();
    00816         }
    00817
    00818         #region Message handling
    00819         private static bool isDragging;
    00823         public bool MessageProc(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
    00824         {
    00825             // If caption is enable, check for clicks in the caption area.
    00826             if (hasCaption)
    00827             {
    00828                 if (msg == NativeMethods.WindowMessage.LeftButtonDown || msg == NativeMethods.WindowMessage.LeftButtonDoubleClick)
    00829                 {
    00830                     // Current mouse position
    00831                     short mouseX = NativeMethods.LoWord((uint)lParam.ToInt32());
    00832                     short mouseY = NativeMethods.HiWord((uint)lParam.ToInt32());
    00833
    00834                     if (mouseX >= dialogX && mouseX < dialogX + width &&
    00835                         mouseY >= dialogY && mouseY < dialogY + captionHeight)
    00836                     {
    00837                         isDragging = true;
    00838                         NativeMethods.SetCapture(hWnd);
    00839                         return true;
    00840                     }
    00841                 }
    00842                 else if ( (msg == NativeMethods.WindowMessage.LeftButtonUp) && isDragging)
    00843                 {
    00844                     // Current mouse position
    00845                     short mouseX = NativeMethods.LoWord((uint)lParam.ToInt32());
    00846                     short mouseY = NativeMethods.HiWord((uint)lParam.ToInt32());
    00847
    00848                     if (mouseX >= dialogX && mouseX < dialogX + width &&
    00849                         mouseY >= dialogY && mouseY < dialogY + captionHeight)
    00850                     {
    00851                         NativeMethods.ReleaseCapture();
    00852                         isDragging = false;
    00853                         return true;
    00854                     }
    00855                 }
    00856             }
    00857
    00858             // If the dialog is minimized, don't send any messages to controls.
    00859             if (isDialogMinimized)
    00860                 return false;
    00861
    00862             // If a control is in focus, it belongs to this dialog, and it's enabled, then give
    00863             // it the first chance at handling the message.
    00864             if (controlFocus != null &&
    00865                 controlFocus.Parent == this &&
    00866                 controlFocus.IsEnabled)
    00867             {
    00868                 // If the control MsgProc handles it, then we don't.
    00869                 if (controlFocus.MsgProc(hWnd, msg, wParam, lParam))
    00870                     return true;
    00871             }
    00872
    00873             switch(msg)
    00874             {
    00875                 // Call OnFocusIn()/OnFocusOut() of the control that currently has the focus
    00876                 // as the application is activated/deactivated.  This matches the Windows
    00877                 // behavior.
    00878                 case NativeMethods.WindowMessage.ActivateApplication:
    00879                 {
    00880                     if (controlFocus != null &&
    00881                         controlFocus.Parent == this &&
    00882                         controlFocus.IsEnabled)
    00883                     {
    00884                         if (wParam != IntPtr.Zero)
    00885                             controlFocus.OnFocusIn();
    00886                         else
    00887                             controlFocus.OnFocusOut();
    00888                     }
    00889                 }
    00890                     break;
    00891
    00892                 // Keyboard messages
    00893                 case NativeMethods.WindowMessage.KeyDown:
    00894                 case NativeMethods.WindowMessage.SystemKeyDown:
    00895                 case NativeMethods.WindowMessage.KeyUp:
    00896                 case NativeMethods.WindowMessage.SystemKeyUp:
    00897                 {
    00898                     // If a control is in focus, it belongs to this dialog, and it's enabled, then give
    00899                     // it the first chance at handling the message.
    00900                     if (controlFocus != null &&
    00901                         controlFocus.Parent == this &&
    00902                         controlFocus.IsEnabled)
    00903                     {
    00904                         // If the control MsgProc handles it, then we don't.
    00905                         if (controlFocus.HandleKeyboard(msg, wParam, lParam))
    00906                             return true;
    00907                     }
    00908
    00909                     // Not yet handled, see if this matches a control's hotkey
    00910                     if (msg == NativeMethods.WindowMessage.KeyUp)
    00911                     {
    00912                         foreach(Control c in controlList)
    00913                         {
    00914                             // Was the hotkey hit?
    00915                             if (c.Hotkey == (System.Windows.Forms.Keys)wParam.ToInt32())
    00916                             {
    00917                                 // Yup!
    00918                                 c.OnHotKey();
    00919                                 return true;
    00920                             }
    00921                         }
    00922                     }
    00923                     if (msg == NativeMethods.WindowMessage.KeyDown)
    00924                     {
    00925                         // If keyboard input is not enabled, this message should be ignored
    00926                         if (!usingKeyboardInput)
    00927                             return false;
    00928
    00929                         System.Windows.Forms.Keys key = (System.Windows.Forms.Keys)wParam.ToInt32();
    00930                         switch(key)
    00931                         {
    00932                             case System.Windows.Forms.Keys.Right:
    00933                             case System.Windows.Forms.Keys.Down:
    00934                                 if (controlFocus != null)
    00935                                 {
    00936                                     OnCycleFocus(true);
    00937                                     return true;
    00938                                 }
    00939                                 break;
    00940                             case System.Windows.Forms.Keys.Left:
    00941                             case System.Windows.Forms.Keys.Up:
    00942                                 if (controlFocus != null)
    00943                                 {
    00944                                     OnCycleFocus(false);
    00945                                     return true;
    00946                                 }
    00947                                 break;
    00948                             case System.Windows.Forms.Keys.Tab:
    00949                                 if (controlFocus == null)
    00950                                 {
    00951                                     FocusDefaultControl();
    00952                                 }
    00953                                 else
    00954                                 {
    00955                                     bool shiftDown = NativeMethods.IsKeyDown(System.Windows.Forms.Keys.ShiftKey);
    00956
    00957                                     OnCycleFocus(!shiftDown);
    00958                                 }
    00959                                 return true;
    00960                         }
    00961                     }
    00962                 }
    00963                     break;
    00964
    00965                 // Mouse messages
    00966                 case NativeMethods.WindowMessage.MouseMove:
    00967                 case NativeMethods.WindowMessage.MouseWheel:
    00968                 case NativeMethods.WindowMessage.LeftButtonUp:
    00969                 case NativeMethods.WindowMessage.LeftButtonDown:
    00970                 case NativeMethods.WindowMessage.LeftButtonDoubleClick:
    00971                 case NativeMethods.WindowMessage.RightButtonUp:
    00972                 case NativeMethods.WindowMessage.RightButtonDown:
    00973                 case NativeMethods.WindowMessage.RightButtonDoubleClick:
    00974                 case NativeMethods.WindowMessage.MiddleButtonUp:
    00975                 case NativeMethods.WindowMessage.MiddleButtonDown:
    00976                 case NativeMethods.WindowMessage.MiddleButtonDoubleClick:
    00977                 case NativeMethods.WindowMessage.XButtonUp:
    00978                 case NativeMethods.WindowMessage.XButtonDown:
    00979                 case NativeMethods.WindowMessage.XButtonDoubleClick:
    00980                 {
    00981                     // If not accepting mouse input, return false to indicate the message should still
    00982                     // be handled by the application (usually to move the camera).
    00983                     if (!usingMouseInput)
    00984                         return false;
    00985
    00986                     // Current mouse position
    00987                     short mouseX = NativeMethods.LoWord((uint)lParam.ToInt32());
    00988                     short mouseY = NativeMethods.HiWord((uint)lParam.ToInt32());
    00989                     System.Drawing.Point mousePoint = new System.Drawing.Point(mouseX, mouseY);
    00990                     // Offset mouse point
    00991                     mousePoint.X -= dialogX;
    00992                     mousePoint.Y -= dialogY;
    00993
    00994                     // If caption is enabled, offset the Y coordinate by the negative of its height.
    00995                     if (hasCaption)
    00996                         mousePoint.Y -= captionHeight;
    00997
    00998                     // If a control is in focus, it belongs to this dialog, and it's enabled, then give
    00999                     // it the first chance at handling the message.
    01000                     if (controlFocus != null &&
    01001                         controlFocus.Parent == this &&
    01002                         controlFocus.IsEnabled)
    01003                     {
    01004                         // If the control MsgProc handles it, then we don't.
    01005                         if (controlFocus.HandleMouse(msg, mousePoint, wParam, lParam))
    01006                             return true;
    01007                     }
    01008
    01009                     // Not yet handled, see if the mouse is over any controls
    01010                     Control control = GetControlAtPoint(mousePoint);
    01011                     if ((control != null) && (control.IsEnabled))
    01012                     {
    01013                         // Let the control handle the mouse if it wants (and return true if it handles it)
    01014                         if (control.HandleMouse(msg, mousePoint, wParam, lParam))
    01015                             return true;
    01016                     }
    01017                     else
    01018                     {
    01019                         // Mouse not over any controls in this dialog, if there was a control
    01020                         // which had focus it just lost it
    01021                         if (msg == NativeMethods.WindowMessage.LeftButtonDown &&
    01022                             controlFocus != null &&
    01023                             controlFocus.Parent == this)
    01024                         {
    01025                             controlFocus.OnFocusOut();
    01026                             controlFocus = null;
    01027                         }
    01028                     }
    01029
    01030                     // Still not handled, hand this off to the dialog. Return false to indicate the
    01031                     // message should still be handled by the application (usually to move the camera).
    01032                     switch(msg)
    01033                     {
    01034                         case NativeMethods.WindowMessage.MouseMove:
    01035                             OnMouseMove(mousePoint);
    01036                             return false;
    01037                     }
    01038
    01039
    01040                 }
    01041                     break;
    01042             }
    01043
    01044             // Didn't handle this message
    01045             return false;
    01046         }
    01047
    01051         private void OnMouseMove(System.Drawing.Point pt)
    01052         {
    01053             // If the mouse was previously hovering over a control, it's either
    01054             // still over the control or has left
    01055             if (controlMouseDown != null)
    01056             {
    01057                 // If another dialog owns this control then let that dialog handle it
    01058                 if (controlMouseDown.Parent != this )
    01059                     return;
    01060
    01061                 // If the same control is still under the mouse, nothing needs to be done
    01062                 if (controlMouseDown.ContainsPoint(pt))
    01063                     return;
    01064
    01065                 // Mouse has moved outside the control, notify the control and continue
    01066                 controlMouseDown.OnMouseExit();
    01067                 controlMouseDown = null;
    01068             }
    01069
    01070             // Figure out which control the mouse is over now
    01071             Control control = GetControlAtPoint(pt);
    01072             if (control != null)
    01073             {
    01074                 controlMouseDown = control;
    01075                 controlMouseDown.OnMouseEnter();
    01076             }
    01077         }
    01078         #endregion
    01079
    01080         #region Focus
    01084         public static void RequestFocus(Control control)
    01085         {
    01086             if (controlFocus == control)
    01087                 return; // Already does
    01088
    01089             if (!control.CanHaveFocus)
    01090                 return; // Can't have focus
    01091
    01092             if (controlFocus != null)
    01093                 controlFocus.OnFocusOut();
    01094
    01095             // Set the control focus now
    01096             control.OnFocusIn();
    01097             controlFocus = control;
    01098         }
    01099
    01103         public static void ClearFocus()
    01104         {
    01105             if (controlFocus != null)
    01106             {
    01107                 controlFocus.OnFocusOut();
    01108                 controlFocus = null;
    01109             }
    01110         }
    01114         private void OnCycleFocus(bool forward)
    01115         {
    01116             // This should only be handled by the dialog which owns the focused control, and
    01117             // only if a control currently has focus
    01118             if (controlFocus == null || controlFocus.Parent != this )
    01119                 return;
    01120
    01121             Control control = controlFocus;
    01122             // Go through a bunch of controls
    01123             for (int i = 0; i < 0xffff; i++)
    01124             {
    01125                 control = (forward) ? GetNextControl(control) : GetPreviousControl(control);
    01126
    01127                 // If we've gone in a full circle, focus won't change
    01128                 if (control == controlFocus)
    01129                     return;
    01130
    01131                 // If the dialog accepts keybord input and the control can have focus then
    01132                 // move focus
    01133                 if (control.Parent.IsUsingKeyboardInput && control.CanHaveFocus)
    01134                 {
    01135                     controlFocus.OnFocusOut();
    01136                     controlFocus = control;
    01137                     controlFocus.OnFocusIn();
    01138                     return;
    01139                 }
    01140             }
    01141
    01142             throw new InvalidOperationException("Multiple dialogs are improperly chained together.");
    01143         }
    01144
    01148         private static Control GetNextControl(Control control)
    01149         {
    01150             int index = (int)control.index + 1;
    01151
    01152             Dialog dialog = control.Parent;
    01153
    01154             // Cycle through dialogs in the loop to find the next control. Note
    01155             // that if only one control exists in all looped dialogs it will
    01156             // be the returned 'next' control.
    01157             while (index >= (int)dialog.controlList.Count)
    01158             {
    01159                 dialog = dialog.nextDialog;
    01160                 index = 0;
    01161             }
    01162
    01163             return dialog.controlList[index] as Control;
    01164         }
    01168         private static Control GetPreviousControl(Control control)
    01169         {
    01170             int index = (int)control.index - 1;
    01171
    01172             Dialog dialog = control.Parent;
    01173
    01174             // Cycle through dialogs in the loop to find the next control. Note
    01175             // that if only one control exists in all looped dialogs it will
    01176             // be the returned 'previous' control.
    01177             while (index < 0)
    01178             {
    01179                 dialog = dialog.prevDialog;
    01180                 if (dialog == null)
    01181                     dialog = control.Parent;
    01182
    01183                 index = dialog.controlList.Count - 1;
    01184             }
    01185
    01186             return dialog.controlList[index] as Control;
    01187         }
    01191         private void FocusDefaultControl()
    01192         {
    01193             // Check for a default control in this dialog
    01194             foreach(Control c in controlList)
    01195             {
    01196                 if (c.isDefault)
    01197                 {
    01198                     // Remove focus from the current control
    01199                     ClearFocus();
    01200
    01201                     // Give focus to the default control
    01202                     controlFocus = c;
    01203                     controlFocus.OnFocusIn();
    01204                     return;
    01205                 }
    01206             }
    01207         }
    01208         #endregion
    01209
    01210         #region Controls Methods/Properties
    01212         public void SetControlEnable(int id, bool isenabled)
    01213         {
    01214             Control c = GetControl(id);
    01215             if (c == null)
    01216                 return; // No control to set
    01217
    01218             c.IsEnabled = isenabled;
    01219         }
    01221         public bool GetControlEnable(int id)
    01222         {
    01223             Control c = GetControl(id);
    01224             if (c == null)
    01225                 return false; // No control to get
    01226
    01227             return c.IsEnabled;
    01228         }
    01229
    01231         public Control GetControlAtPoint(System.Drawing.Point pt)
    01232         {
    01233             foreach(Control c in controlList)
    01234             {
    01235                 if (c == null)
    01236                     continue;
    01237
    01238                 if (c.IsEnabled && c.IsVisible && c.ContainsPoint(pt))
    01239                     return c;
    01240             }
    01241
    01242             return null;
    01243         }
    01245         public Control GetControl(int id)
    01246         {
    01247             foreach(Control c in controlList)
    01248             {
    01249                 if (c == null)
    01250                     continue;
    01251
    01252                 if (c.ID == id)
    01253                     return c;
    01254             }
    01255
    01256             return null;
    01257         }
    01259         public Control GetControl(int id, ControlType typeControl)
    01260         {
    01261             foreach(Control c in controlList)
    01262             {
    01263                 if (c == null)
    01264                     continue;
    01265
    01266                 if ((c.ID == id) && (c.ControlType == typeControl))
    01267                     return c;
    01268             }
    01269
    01270             return null;
    01271         }
    01272
    01274         public StaticText GetStaticText(int id) { return GetControl(id, ControlType.StaticText) as StaticText; }
    01276         public Button GetButton(int id) { return GetControl(id, ControlType.Button) as Button; }
    01278         public Checkbox GetCheckbox(int id) { return GetControl(id, ControlType.CheckBox) as Checkbox; }
    01280         public RadioButton GetRadioButton(int id) { return GetControl(id, ControlType.RadioButton) as RadioButton; }
    01282         public ComboBox GetComboBox(int id) { return GetControl(id, ControlType.ComboBox) as ComboBox; }
    01284         public Slider GetSlider(int id) { return GetControl(id, ControlType.Slider) as Slider; }
    01286         public ListBox GetListBox(int id) { return GetControl(id, ControlType.ListBox) as ListBox; }
    01287         #endregion
    01288
    01289         #region Default Elements
    01293         public void SetDefaultElement(ControlType ctype, uint index, Element e)
    01294         {
    01295             // If this element already exists, just update it
    01296             for (int i = 0; i < defaultElementList.Count; i++)
    01297             {
    01298                 ElementHolder holder = (ElementHolder)defaultElementList[i];
    01299                 if ( (holder.ControlType == ctype) &&
    01300                     (holder.ElementIndex == index) )
    01301                 {
    01302                     // Found it, update it
    01303                     holder.Element = e.Clone();
    01304                     defaultElementList[i] = holder;
    01305                     return;
    01306                 }
    01307             }
    01308
    01309             // Couldn't find it, add a new entry
    01310             ElementHolder newEntry = new ElementHolder();
    01311             newEntry.ControlType = ctype;
    01312             newEntry.ElementIndex = index;
    01313             newEntry.Element = e.Clone();
    01314
    01315             // Add it now
    01316             defaultElementList.Add(newEntry);
    01317         }
    01321         public Element GetDefaultElement(ControlType ctype, uint index)
    01322         {
    01323             for (int i = 0; i < defaultElementList.Count; i++)
    01324             {
    01325                 ElementHolder holder = (ElementHolder)defaultElementList[i];
    01326                 if ( (holder.ControlType == ctype) &&
    01327                     (holder.ElementIndex == index) )
    01328                 {
    01329                     // Found it, return it
    01330                     return holder.Element;
    01331                 }
    01332             }
    01333             return null;
    01334         }
    01335         #endregion
    01336
    01337         #region Texture/Font Resources
    01342         public void SetFont(uint index, string faceName, uint height, FontWeight weight)
    01343         {
    01344             // Make sure the list is at least big enough to hold this index
    01345             for (uint i = (uint)fontList.Count; i <= index; i++)
    01346                 fontList.Add((int)(-1));
    01347
    01348             int fontIndex = DialogResourceManager.GetGlobalInstance().AddFont(faceName, height, weight);
    01349             fontList[(int)index] = fontIndex;
    01350         }
    01355         public FontNode GetFont(uint index)
    01356         {
    01357             return DialogResourceManager.GetGlobalInstance().GetFontNode((int)fontList[(int)index]);
    01358         }
    01363         public void SetTexture(uint index, string filename)
    01364         {
    01365             // Make sure the list is at least big enough to hold this index
    01366             for (uint i = (uint)textureList.Count; i <= index; i++)
    01367                 textureList.Add((int)(-1));
    01368
    01369             int textureIndex = DialogResourceManager.GetGlobalInstance().AddTexture(filename);
    01370             textureList[(int)index] = textureIndex;
    01371         }
    01376         public TextureNode GetTexture(uint index)
    01377         {
    01378             return DialogResourceManager.GetGlobalInstance().GetTextureNode((int)textureList[(int)index]);
    01379         }
    01380         #endregion
    01381
    01382         #region Control Creation
    01386         public void InitializeControl(Control control)
    01387         {
    01388             if (control == null)
    01389                 throw new ArgumentNullException("control", "You cannot pass in a null control to initialize");
    01390
    01391             // Set the index
    01392             control.index = (uint)controlList.Count;
    01393
    01394             // Look for a default element entires
    01395             for (int i = 0; i < defaultElementList.Count; i++)
    01396             {
    01397                 // Find any elements for this control
    01398                 ElementHolder holder = (ElementHolder)defaultElementList[i];
    01399                 if (holder.ControlType == control.ControlType)
    01400                     control[holder.ElementIndex] = holder.Element;
    01401             }
    01402
    01403             // Initialize the control
    01404             control.OnInitialize();
    01405         }
    01409         public void AddControl(Control control)
    01410         {
    01411             // Initialize the control first
    01412             InitializeControl(control);
    01413
    01414             // Add this to the control list
    01415             controlList.Add(control);
    01416         }
    01418         public StaticText AddStatic(int id, string text, int x, int y, int w, int h, bool isDefault)
    01419         {
    01420             // First create the static
    01421             StaticText s = new StaticText(this);
    01422
    01423             // Now call the add control method
    01424             AddControl(s);
    01425
    01426             // Set the properties of the static now
    01427             s.ID = id;
    01428             s.SetText(text);
    01429             s.SetLocation(x, y);
    01430             s.SetSize(w,h);
    01431             s.isDefault = isDefault;
    01432
    01433             return s;
    01434         }
    01436         public StaticText AddStatic(int id, string text, int x, int y, int w, int h){return AddStatic(id, text, x, y, w, h, false); }
    01438         public Button AddButton(int id, string text, int x, int y, int w, int h, System.Windows.Forms.Keys hotkey, bool isDefault)
    01439         {
    01440             // First create the button
    01441             Button b = new Button(this);
    01442
    01443             // Now call the add control method
    01444             AddControl(b);
    01445
    01446             // Set the properties of the button now
    01447             b.ID = id;
    01448             b.SetText(text);
    01449             b.SetLocation(x, y);
    01450             b.SetSize(w,h);
    01451             b.Hotkey = hotkey;
    01452             b.isDefault = isDefault;
    01453
    01454             return b;
    01455         }
    01457         public Button AddButton(int id, string text, int x, int y, int w, int h) { return AddButton(id, text, x, y, w, h, 0, false); }
    01459         public Checkbox AddCheckBox(int id, string text, int x, int y, int w, int h, bool ischecked, System.Windows.Forms.Keys hotkey, bool isDefault)
    01460         {
    01461             // First create the checkbox
    01462             Checkbox c = new Checkbox(this);
    01463
    01464             // Now call the add control method
    01465             AddControl(c);
    01466
    01467             // Set the properties of the button now
    01468             c.ID = id;
    01469             c.SetText(text);
    01470             c.SetLocation(x, y);
    01471             c.SetSize(w,h);
    01472             c.Hotkey = hotkey;
    01473             c.isDefault = isDefault;
    01474             c.IsChecked = ischecked;
    01475
    01476             return c;
    01477         }
    01479         public Checkbox AddCheckBox(int id, string text, int x, int y, int w, int h, bool ischecked) { return AddCheckBox(id, text, x, y, w, h, ischecked, 0, false); }
    01481         public RadioButton AddRadioButton(int id, uint groupId, string text, int x, int y, int w, int h, bool ischecked, System.Windows.Forms.Keys hotkey, bool isDefault)
    01482         {
    01483             // First create the RadioButton
    01484             RadioButton c = new RadioButton(this);
    01485
    01486             // Now call the add control method
    01487             AddControl(c);
    01488
    01489             // Set the properties of the button now
    01490             c.ID = id;
    01491             c.ButtonGroup = groupId;
    01492             c.SetText(text);
    01493             c.SetLocation(x, y);
    01494             c.SetSize(w,h);
    01495             c.Hotkey = hotkey;
    01496             c.isDefault = isDefault;
    01497             c.IsChecked = ischecked;
    01498
    01499             return c;
    01500         }
    01502         public RadioButton AddRadioButton(int id, uint groupId, string text, int x, int y, int w, int h, bool ischecked) { return AddRadioButton(id, groupId, text, x, y, w, h, ischecked, 0, false); }
    01504         public ComboBox AddComboBox(int id, int x, int y, int w, int h, System.Windows.Forms.Keys hotkey, bool isDefault)
    01505         {
    01506             // First create the combo
    01507             ComboBox c = new ComboBox(this);
    01508
    01509             // Now call the add control method
    01510             AddControl(c);
    01511
    01512             // Set the properties of the button now
    01513             c.ID = id;
    01514             c.SetLocation(x, y);
    01515             c.SetSize(w,h);
    01516             c.Hotkey = hotkey;
    01517             c.isDefault = isDefault;
    01518
    01519             return c;
    01520         }
    01522         public ComboBox AddComboBox(int id, int x, int y, int w, int h) { return AddComboBox(id, x, y, w, h, 0, false); }
    01524         public Slider AddSlider(int id, int x, int y, int w, int h, int min, int max, int initialValue, bool isDefault)
    01525         {
    01526             // First create the slider
    01527             Slider c = new Slider(this);
    01528
    01529             // Now call the add control method
    01530             AddControl(c);
    01531
    01532             // Set the properties of the button now
    01533             c.ID = id;
    01534             c.SetLocation(x, y);
    01535             c.SetSize(w,h);
    01536             c.isDefault = isDefault;
    01537             c.SetRange(min, max);
    01538             c.Value = initialValue;
    01539
    01540             return c;
    01541         }
    01543         public Slider AddSlider(int id, int x, int y, int w, int h) { return AddSlider(id, x, y, w, h, 0,100,50, false); }
    01545         public ListBox AddListBox(int id, int x, int y, int w, int h, ListBoxStyle style)
    01546         {
    01547             // First create the listbox
    01548             ListBox c = new ListBox(this);
    01549
    01550             // Now call the add control method
    01551             AddControl(c);
    01552
    01553             // Set the properties of the button now
    01554             c.ID = id;
    01555             c.SetLocation(x, y);
    01556             c.SetSize(w,h);
    01557             c.Style = style;
    01558
    01559             return c;
    01560         }
    01562         public ListBox AddListBox(int id, int x, int y, int w, int h) { return AddListBox(id, x, y, w, h, ListBoxStyle.SingleSelection); }
    01564         public EditBox AddEditBox(int id, string text, int x, int y, int w, int h, bool isDefault)
    01565         {
    01566             // First create the editbox
    01567             EditBox c = new EditBox(this);
    01568
    01569             // Now call the add control method
    01570             AddControl(c);
    01571
    01572             // Set the properties of the static now
    01573             c.ID = id;
    01574             c.Text = (text != null) ? text : string.Empty;
    01575             c.SetLocation(x, y);
    01576             c.SetSize(w,h);
    01577             c.isDefault = isDefault;
    01578
    01579             return c;
    01580         }
    01582         public EditBox AddEditBox(int id, string text, int x, int y, int w, int h){return AddEditBox(id, text, x, y, w, h, false); }
    01583         #endregion
    01584
    01586         private void UpdateVertices()
    01587         {
    01588             vertices = new Microsoft.DirectX.Direct3D.CustomVertex.TransformedColoredTextured[] {
    01589                 new CustomVertex.TransformedColoredTextured(dialogX,dialogY,0.5f,1.0f,topLeftColor.ToArgb(),0.0f,0.5f),
    01590                 new CustomVertex.TransformedColoredTextured(dialogX + width,dialogY,0.5f,1.0f,topRightColor.ToArgb(),1.0f,0.5f),
    01591                 new CustomVertex.TransformedColoredTextured(dialogX+width,dialogY+height,0.5f,1.0f,bottomRightColor.ToArgb(),1.0f,1.0f),
    01592                 new CustomVertex.TransformedColoredTextured(dialogX,dialogY+height,0.5f,1.0f,bottomLeftColor.ToArgb(),0.0f,1.0f)
    01593             };
    01594         }
    01595         #region Drawing methods
    01597         public void OnRender(float elapsedTime)
    01598         {
    01599             // See if the dialog needs to be refreshed
    01600             if (timeLastRefresh < timeRefresh)
    01601             {
    01602                 timeLastRefresh = FrameworkTimer.GetTime();
    01603                 Refresh();
    01604             }
    01605
    01606             Device device = DialogResourceManager.GetGlobalInstance().Device;
    01607
    01608             // Set up a state block here and restore it when finished drawing all the controls
    01609             DialogResourceManager.GetGlobalInstance().StateBlock.Capture();
    01610
    01611             // Set some render/texture states
    01612             device.RenderState.AlphaBlendEnable = true;
    01613             device.RenderState.SourceBlend = Blend.SourceAlpha;
    01614             device.RenderState.DestinationBlend = Blend.InvSourceAlpha;
    01615             device.RenderState.AlphaTestEnable = false;
    01616             device.TextureState[0].ColorOperation = TextureOperation.SelectArg2;
    01617             device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
    01618             device.TextureState[0].AlphaOperation = TextureOperation.SelectArg1;
    01619             device.TextureState[0].AlphaArgument1 = TextureArgument.Diffuse;
    01620             device.RenderState.ZBufferEnable = false;
    01621             // Clear vertex/pixel shader
    01622             device.VertexShader = null;
    01623             device.PixelShader = null;
    01624
    01625             // Render if not minimized
    01626             if (!isDialogMinimized)
    01627             {
    01628                 device.VertexFormat = CustomVertex.TransformedColoredTextured.Format;
    01629                 device.DrawUserPrimitives(PrimitiveType.TriangleFan, 2, vertices);
    01630             }
    01631
    01632             // Reset states
    01633             device.TextureState[0].ColorOperation = TextureOperation.Modulate;
    01634             device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
    01635             device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
    01636             device.TextureState[0].AlphaOperation = TextureOperation.Modulate;
    01637             device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
    01638             device.TextureState[0].AlphaArgument2 = TextureArgument.Diffuse;
    01639
    01640             device.SamplerState[0].MinFilter = TextureFilter.Linear;
    01641
    01642             // Set the texture up, and begin the sprite
    01643             TextureNode tNode = GetTexture(0);
    01644             device.SetTexture(0, tNode.Texture);
    01645             DialogResourceManager.GetGlobalInstance().Sprite.Begin(SpriteFlags.DoNotSaveState);
    01646
    01647             // Render the caption if it's enabled.
    01648             if (hasCaption)
    01649             {
    01650                 // DrawSprite will offset the rect down by
    01651                 // captionHeight, so adjust the rect higher
    01652                 // here to negate the effect.
    01653                 System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0,-captionHeight,width,0);
    01654                 DrawSprite(captionElement, rect);
    01655                 rect.Offset(5, 0); // Make a left margin
    01656                 string output = caption + ((isDialogMinimized) ? " (Minimized)" : null);
    01657                 DrawText(output, captionElement, rect, true);
    01658             }
    01659
    01660             // If the dialog is minimized, skip rendering
    01661             // its controls.
    01662             if (!isDialogMinimized)
    01663             {
    01664                 for(int i = 0; i < controlList.Count; i++)
    01665                 {
    01666                     // Focused control is drawn last
    01667                     if (controlList[i] == controlFocus)
    01668                         continue;
    01669
    01670                     (controlList[i] as Control).Render(device, elapsedTime);
    01671                 }
    01672
    01673                 // Render the focus control if necessary
    01674                 if (controlFocus != null && controlFocus.Parent == this)
    01675                     controlFocus.Render(device, elapsedTime);
    01676             }
    01677
    01678             // End the sprite and apply the stateblock
    01679             DialogResourceManager.GetGlobalInstance().Sprite.End();
    01680             DialogResourceManager.GetGlobalInstance().StateBlock.Apply();
    01681         }
    01682
    01686         private void Refresh()
    01687         {
    01688             // Reset the controls
    01689             if (controlFocus != null)
    01690                 controlFocus.OnFocusOut();
    01691
    01692             if (controlMouseOver != null)
    01693                 controlMouseOver.OnMouseExit();
    01694
    01695             controlFocus = null;
    01696             controlMouseDown = null;
    01697             controlMouseOver = null;
    01698
    01699             // Refresh any controls
    01700             foreach(Control c in controlList)
    01701             {
    01702                 c.Refresh();
    01703             }
    01704
    01705             if (usingKeyboardInput)
    01706                 FocusDefaultControl();
    01707         }
    01708
    01710         public void DrawText(string text, Element element, System.Drawing.Rectangle rect, bool shadow)
    01711         {
    01712             // No need to draw fully transparant layers
    01713             if (element.FontColor.Current.Alpha == 0)
    01714                 return; // Nothing to do
    01715
    01716             System.Drawing.Rectangle screenRect = rect;
    01717             screenRect.Offset(dialogX, dialogY);
    01718
    01719             // If caption is enabled, offset the Y position by its height.
    01720             if (hasCaption)
    01721                 screenRect.Offset(0, captionHeight);
    01722
    01723             // Set the identity transform
    01724             DialogResourceManager.GetGlobalInstance().Sprite.Transform = Matrix.Identity;
    01725
    01726             // Get the font node here
    01727             FontNode fNode = GetFont(element.FontIndex);
    01728             if (shadow)
    01729             {
    01730                 // Render the text shadowed
    01731                 System.Drawing.Rectangle shadowRect = screenRect;
    01732                 shadowRect.Offset(1, 1);
    01733                 fNode.Font.DrawText(DialogResourceManager.GetGlobalInstance().Sprite, text,
    01734                     shadowRect, element.textFormat, unchecked((int)0xff000000));
    01735             }
    01736
    01737             fNode.Font.DrawText(DialogResourceManager.GetGlobalInstance().Sprite, text,
    01738                 screenRect, element.textFormat, element.FontColor.Current.ToArgb());
    01739         }
    01741         public void DrawSprite(Element element, System.Drawing.Rectangle rect)
    01742         {
    01743             // No need to draw fully transparant layers
    01744             if (element.TextureColor.Current.Alpha == 0)
    01745                 return; // Nothing to do
    01746
    01747             System.Drawing.Rectangle texRect = element.textureRect;
    01748             System.Drawing.Rectangle screenRect = rect;
    01749             screenRect.Offset(dialogX, dialogY);
    01750
    01751             // If caption is enabled, offset the Y position by its height.
    01752             if (hasCaption)
    01753                 screenRect.Offset(0, captionHeight);
    01754
    01755             // Get the texture
    01756             TextureNode tNode = GetTexture(element.TextureIndex);
    01757             float scaleX = (float)screenRect.Width / (float)texRect.Width;
    01758             float scaleY = (float)screenRect.Height / (float)texRect.Height;
    01759
    01760             // Set the scaling transform
    01761             DialogResourceManager.GetGlobalInstance().Sprite.Transform = Matrix.Scaling(scaleX, scaleY, 1.0f);
    01762
    01763             // Calculate the position
    01764             Vector3 pos = new Vector3(screenRect.Left, screenRect.Top, 0.0f);
    01765             pos.X /= scaleX;
    01766             pos.Y /= scaleY;
    01767
    01768             // Finally draw the sprite
    01769             DialogResourceManager.GetGlobalInstance().Sprite.Draw(tNode.Texture, texRect, new Vector3(), pos, element.TextureColor.Current.ToArgb());
    01770         }
    01772         public void DrawText(string text, Element element, System.Drawing.Rectangle rect) { this.DrawText(text, element, rect, false); }
    01774         public void DrawRectangle(System.Drawing.Rectangle rect, ColorValue color)
    01775         {
    01776             // Offset the rectangle
    01777             rect.Offset(dialogX, dialogY);
    01778
    01779             // If caption is enabled, offset the Y position by its height
    01780             if (hasCaption)
    01781                 rect.Offset(0, captionHeight);
    01782
    01783             // Get the integer value of the color
    01784             int realColor = color.ToArgb();
    01785             // Create some vertices
    01786             CustomVertex.TransformedColoredTextured[] verts = {
    01787                 new CustomVertex.TransformedColoredTextured((float)rect.Left - 0.5f, (float)rect.Top -0.5f, 0.5f, 1.0f, realColor, 0, 0),
    01788                 new CustomVertex.TransformedColoredTextured((float)rect.Right - 0.5f, (float)rect.Top -0.5f, 0.5f, 1.0f, realColor, 0, 0),
    01789                 new CustomVertex.TransformedColoredTextured((float)rect.Right - 0.5f, (float)rect.Bottom -0.5f, 0.5f, 1.0f, realColor, 0, 0),
    01790                 new CustomVertex.TransformedColoredTextured((float)rect.Left - 0.5f, (float)rect.Bottom -0.5f, 0.5f, 1.0f, realColor, 0, 0),
    01791             };
    01792
    01793             // Get the device
    01794             Device device = SampleFramework.Device;
    01795
    01796             // Since we're doing our own drawing here, we need to flush the sprites
    01797             DialogResourceManager.GetGlobalInstance().Sprite.Flush();
    01798             // Preserve the devices current vertex declaration
    01799             using (VertexDeclaration decl = device.VertexDeclaration)
    01800             {
    01801                 // Set the vertex format
    01802                 device.VertexFormat = CustomVertex.TransformedColoredTextured.Format;
    01803
    01804                 // Set some texture states
    01805                 device.TextureState[0].ColorOperation = TextureOperation.SelectArg2;
    01806                 device.TextureState[0].AlphaOperation = TextureOperation.SelectArg2;
    01807
    01808                 // Draw the rectangle
    01809                 device.DrawUserPrimitives(PrimitiveType.TriangleFan, 2, verts);
    01810
    01811                 // Reset some texture states
    01812                 device.TextureState[0].ColorOperation = TextureOperation.Modulate;
    01813                 device.TextureState[0].AlphaOperation = TextureOperation.Modulate;
    01814
    01815                 // Restore the vertex declaration
    01816                 device.VertexDeclaration = decl;
    01817             }
    01818         }
    01819         #endregion
    01820
    01821     }
    01822
    01823     #region Abstract Control class
    01825     public abstract class Control
    01826     {
    01827         #region Instance data
    01828         protected Dialog parentDialog; // Parent container
    01829         public uint index; // Index within the control list
    01830         public bool isDefault;
    01831
    01832         // Protected members
    01833         protected object localUserData; // User specificied data
    01834         protected bool visible;
    01835         protected bool isMouseOver;
    01836         protected bool hasFocus;
    01837         protected int controlId; // ID Number
    01838         protected ControlType controlType; // Control type, set in constructor
    01839         protected System.Windows.Forms.Keys hotKey; // Controls hotkey
    01840         protected bool enabled; // Enabled/disabled flag
    01841         protected System.Drawing.Rectangle boundingBox; // Rectangle defining the active region of the control
    01842
    01843         protected int controlX,controlY,width,height; // Size, scale, and positioning members
    01844
    01845         protected ArrayList elementList = new ArrayList(); // All display elements
    01846         #endregion
    01847
    01849         public virtual void OnInitialize() {} // Nothing to do here
    01851         public virtual void Render(Device device, float elapsedTime) {} // Nothing to do here
    01853         public virtual bool MsgProc(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam) {return false;} // Nothing to do here
    01855         public virtual bool HandleKeyboard(NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam) {return false;} // Nothing to do here
    01857         public virtual bool HandleMouse(NativeMethods.WindowMessage msg, System.Drawing.Point pt, IntPtr wParam, IntPtr lParam) {return false;} // Nothing to do here
    01858
    01860         public object UserData { get { return localUserData; } set { localUserData = value; } }
    01862         public Dialog Parent { get { return parentDialog; } }
    01864         public virtual bool CanHaveFocus { get { return false; } }
    01866         public virtual void OnFocusIn() { hasFocus = true;}
    01868         public virtual void OnFocusOut() { hasFocus = false;}
    01870         public virtual void OnMouseEnter() { isMouseOver = true;}
    01872         public virtual void OnMouseExit() { isMouseOver = false;}
    01874         public virtual void OnHotKey() {} // Nothing to do here
    01876         public virtual bool ContainsPoint(System.Drawing.Point pt) { return boundingBox.Contains(pt); }
    01878         public virtual bool IsEnabled { get { return enabled; } set { enabled = value; } }
    01880         public virtual bool IsVisible { get { return visible; } set { visible = value; } }
    01882         public virtual ControlType ControlType { get { return controlType; } }
    01884         public virtual int ID { get { return controlId; } set { controlId = value; } }
    01886         public virtual void SetLocation(int x, int y) { controlX = x; controlY = y; UpdateRectangles(); }
    01888         public virtual void SetSize(int w, int h) { width = w; height = h; UpdateRectangles(); }
    01890         public virtual System.Windows.Forms.Keys Hotkey { get { return hotKey; } set { hotKey = value; } }
    01891
    01895         public Element this[uint index]
    01896         {
    01897             get { return elementList[(int)index] as Element; }
    01898             set
    01899             {
    01900                 if (value == null)
    01901                     throw new ArgumentNullException("ControlIndexer", "You cannot set a null element.");
    01902
    01903                 // Is the collection big enough?
    01904                 for(uint i = (uint)elementList.Count; i <= index; i++)
    01905                 {
    01906                     // Add a new one
    01907                     elementList.Add(new Element());
    01908                 }
    01909                 // Update the data (with a clone)
    01910                 elementList[(int)index] = value.Clone();
    01911             }
    01912         }
    01916         protected Control(Dialog parent)
    01917         {
    01918             controlType = ControlType.Button;
    01919             parentDialog = parent;
    01920             controlId = 0;
    01921             index = 0;
    01922
    01923             enabled = true;
    01924             visible = true;
    01925             isMouseOver = false;
    01926             hasFocus = false;
    01927             isDefault = false;
    01928
    01929             controlX = 0; controlY = 0; width = 0; height = 0;
    01930         }
    01931
    01935         public virtual void Refresh()
    01936         {
    01937             isMouseOver = false;
    01938             hasFocus = false;
    01939             for(int i = 0; i < elementList.Count; i++)
    01940             {
    01941                 (elementList[i] as Element).Refresh();
    01942             }
    01943         }
    01944
    01948         protected virtual void UpdateRectangles()
    01949         {
    01950             boundingBox = new System.Drawing.Rectangle(controlX, controlY, width, height);
    01951         }
    01952     }
    01953     #endregion
    01954
    01955     #region StaticText control
    01959     public class StaticText : Control
    01960     {
    01961         public const int TextElement = 0;
    01962         protected string textData; // Window text
    01963
    01967         public StaticText(Dialog parent) : base(parent)
    01968         {
    01969             controlType = ControlType.StaticText;
    01970             parentDialog = parent;
    01971             textData = string.Empty;
    01972             elementList.Clear();
    01973         }
    01974
    01978         public override void Render(Device device, float elapsedTime)
    01979         {
    01980             if (!IsVisible)
    01981                 return; // Nothing to do here
    01982
    01983             ControlState state = ControlState.Normal;
    01984             if (!IsEnabled)
    01985                 state = ControlState.Disabled;
    01986
    01987             // Blend the element colors
    01988             Element e = elementList[TextElement] as Element;
    01989             e.FontColor.Blend(state, elapsedTime);
    01990
    01991             // Render with a shadow
    01992             parentDialog.DrawText(textData, e, boundingBox, true);
    01993         }
    01994
    01998         public string GetTextCopy()
    01999         {
    02000             return string.Copy(textData);
    02001         }
    02002
    02006         public void SetText(string newText)
    02007         {
    02008             textData = newText;
    02009         }
    02010
    02011     }
    02012     #endregion
    02013
    02014     #region Button control
    02015
    02019     public class Button : StaticText
    02020     {
    02021         public const int ButtonLayer = 0;
    02022         public const int FillLayer = 1;
    02023         protected bool isPressed;
    02024         #region Event code
    02025         public event EventHandler Click;
    02027         protected void RaiseClickEvent(Button sender, bool wasTriggeredByUser)
    02028         {
    02029             // Discard events triggered programatically if these types of events haven't been
    02030             // enabled
    02031             if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
    02032                 return;
    02033
    02034             if (Click != null)
    02035                 Click(sender, EventArgs.Empty);
    02036         }
    02037         #endregion
    02038
    02040         public Button(Dialog parent) : base(parent)
    02041         {
    02042             controlType = ControlType.Button;
    02043             parentDialog = parent;
    02044             isPressed = false;
    02045             hotKey = 0;
    02046         }
    02047
    02049         public override bool CanHaveFocus { get { return IsVisible && IsEnabled; } }
    02051         public override void OnHotKey()
    02052         {
    02053             RaiseClickEvent(this, true);
    02054         }
    02055
    02059         public override bool HandleKeyboard(NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
    02060         {
    02061             if (!IsEnabled || !IsVisible)
    02062                 return false;
    02063
    02064             switch(msg)
    02065             {
    02066                 case NativeMethods.WindowMessage.KeyDown:
    02067                     if ((System.Windows.Forms.Keys)wParam.ToInt32() == System.Windows.Forms.Keys.Space)
    02068                     {
    02069                         isPressed = true;
    02070                         return true;
    02071                     }
    02072                     break;
    02073                 case NativeMethods.WindowMessage.KeyUp:
    02074                     if ((System.Windows.Forms.Keys)wParam.ToInt32() == System.Windows.Forms.Keys.Space)
    02075                     {
    02076                         isPressed = false;
    02077                         RaiseClickEvent(this, true);
    02078
    02079                         return true;
    02080                     }
    02081                     break;
    02082             }
    02083             return false;
    02084         }
    02085
    02089         public override bool HandleMouse(NativeMethods.WindowMessage msg, System.Drawing.Point pt, IntPtr wParam, IntPtr lParam)
    02090         {
    02091             if (!IsEnabled || !IsVisible)
    02092                 return false;
    02093
    02094             switch(msg)
    02095             {
    02096                 case NativeMethods.WindowMessage.LeftButtonDoubleClick:
    02097                 case NativeMethods.WindowMessage.LeftButtonDown:
    02098                 {
    02099                     if (ContainsPoint(pt))
    02100                     {
    02101                         // Pressed while inside the control
    02102                         isPressed = true;
    02103                         Parent.SampleFramework.Window.Capture = true;
    02104                         if (!hasFocus)
    02105                             Dialog.RequestFocus(this);
    02106
    02107                         return true;
    02108                     }
    02109                 }
    02110                     break;
    02111                 case NativeMethods.WindowMessage.LeftButtonUp:
    02112                 {
    02113                     if (isPressed)
    02114                     {
    02115                         isPressed = false;
    02116                         Parent.SampleFramework.Window.Capture = false;
    02117                         if (!parentDialog.IsUsingKeyboardInput)
    02118                             Dialog.ClearFocus();
    02119
    02120                         // Button click
    02121                         if (ContainsPoint(pt))
    02122                             RaiseClickEvent(this, true);
    02123                     }
    02124                 }
    02125                     break;
    02126             }
    02127
    02128             return false;
    02129         }
    02130
    02132         public override void Render(Device device, float elapsedTime)
    02133         {
    02134             int offsetX = 0;
    02135             int offsetY = 0;
    02136
    02137             ControlState state = ControlState.Normal;
    02138             if (IsVisible == false)
    02139             {
    02140                 state = ControlState.Hidden;
    02141             }
    02142             else if (IsEnabled == false)
    02143             {
    02144                 state = ControlState.Disabled;
    02145             }
    02146             else if (isPressed)
    02147             {
    02148                 state = ControlState.Pressed;
    02149                 offsetX = 1;
    02150                 offsetY = 2;
    02151             }
    02152             else if (isMouseOver)
    02153             {
    02154                 state = ControlState.MouseOver;
    02155                 offsetX = -1;
    02156                 offsetY = -2;
    02157             }
    02158             else if (hasFocus)
    02159             {
    02160                 state = ControlState.Focus;
    02161             }
    02162
    02163             // Background fill layer
    02164             Element e = elementList[Button.ButtonLayer] as Element;
    02165             float blendRate = (state == ControlState.Pressed) ? 0.0f : 0.8f;
    02166
    02167             System.Drawing.Rectangle buttonRect = boundingBox;
    02168             buttonRect.Offset(offsetX, offsetY);
    02169
    02170             // Blend current color
    02171             e.TextureColor.Blend(state, elapsedTime, blendRate);
    02172             e.FontColor.Blend(state, elapsedTime, blendRate);
    02173
    02174             // Draw sprite/text of button
    02175             parentDialog.DrawSprite(e, buttonRect);
    02176             parentDialog.DrawText(textData, e, buttonRect);
    02177
    02178             // Main button
    02179             e = elementList[Button.FillLayer] as Element;
    02180
    02181             // Blend current color
    02182             e.TextureColor.Blend(state, elapsedTime, blendRate);
    02183             e.FontColor.Blend(state, elapsedTime, blendRate);
    02184
    02185             parentDialog.DrawSprite(e, buttonRect);
    02186             parentDialog.DrawText(textData, e, buttonRect);
    02187         }
    02188
    02189     }
    02190     #endregion
    02191
    02192     #region Checkbox Control
    02196     public class Checkbox : Button
    02197     {
    02198         public const int BoxLayer = 0;
    02199         public const int CheckLayer = 1;
    02200         #region Event code
    02201         public event EventHandler Changed;
    02203         protected void RaiseChangedEvent(Checkbox sender, bool wasTriggeredByUser)
    02204         {
    02205             // Discard events triggered programatically if these types of events haven't been
    02206             // enabled
    02207             if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
    02208                 return;
    02209
    02210             // Fire both the changed and clicked event
    02211             base.RaiseClickEvent(sender, wasTriggeredByUser);
    02212             if (Changed != null)
    02213                 Changed(sender, EventArgs.Empty);
    02214         }
    02215         #endregion
    02216         protected System.Drawing.Rectangle buttonRect;
    02217         protected System.Drawing.Rectangle textRect;
    02218         protected bool isBoxChecked;
    02219
    02223         public Checkbox(Dialog parent) : base(parent)
    02224         {
    02225             controlType = ControlType.CheckBox;
    02226             isBoxChecked = false;
    02227             parentDialog = parent;
    02228         }
    02229
    02233         public virtual bool IsChecked
    02234         {
    02235             get { return isBoxChecked; }
    02236             set { SetCheckedInternal(value, false); }
    02237         }
    02241         protected virtual void SetCheckedInternal(bool ischecked, bool fromInput)
    02242         {
    02243             isBoxChecked = ischecked;
    02244             RaiseChangedEvent(this, fromInput);
    02245         }
    02246
    02250         public override void OnHotKey()
    02251         {
    02252             SetCheckedInternal(!isBoxChecked, true);
    02253         }
    02254
    02258         public override bool ContainsPoint(System.Drawing.Point pt)
    02259         {
    02260             return (boundingBox.Contains(pt) || buttonRect.Contains(pt));
    02261         }
    02265         protected override void UpdateRectangles()
    02266         {
    02267             // Update base first
    02268             base.UpdateRectangles();
    02269
    02270             // Update the two rects
    02271             buttonRect = boundingBox;
    02272             buttonRect = new System.Drawing.Rectangle(boundingBox.Location,
    02273                 new System.Drawing.Size(boundingBox.Height, boundingBox.Height));
    02274
    02275             textRect = boundingBox;
    02276             textRect.Offset((int) (1.25f * buttonRect.Width), 0);
    02277         }
    02278
    02282         public override void Render(Device device, float elapsedTime)
    02283         {
    02284             ControlState state = ControlState.Normal;
    02285             if (IsVisible == false)
    02286                 state = ControlState.Hidden;
    02287             else if (IsEnabled == false)
    02288                 state = ControlState.Disabled;
    02289             else if (isPressed)
    02290                 state = ControlState.Pressed;
    02291             else if (isMouseOver)
    02292                 state = ControlState.MouseOver;
    02293             else if (hasFocus)
    02294                 state = ControlState.Focus;
    02295
    02296             Element e = elementList[Checkbox.BoxLayer] as Element;
    02297             float blendRate = (state == ControlState.Pressed) ? 0.0f : 0.8f;
    02298
    02299             // Blend current color
    02300             e.TextureColor.Blend(state, elapsedTime, blendRate);
    02301             e.FontColor.Blend(state, elapsedTime, blendRate);
    02302
    02303             // Draw sprite/text of checkbox
    02304             parentDialog.DrawSprite(e, buttonRect);
    02305             parentDialog.DrawText(textData, e, textRect);
    02306
    02307             if (!isBoxChecked)
    02308                 state = ControlState.Hidden;
    02309
    02310             e = elementList[Checkbox.CheckLayer] as Element;
    02311             // Blend current color
    02312             e.TextureColor.Blend(state, elapsedTime, blendRate);
    02313
    02314             // Draw sprite of checkbox
    02315             parentDialog.DrawSprite(e, buttonRect);
    02316         }
    02317
    02321         public override bool HandleKeyboard(NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
    02322         {
    02323             if (!IsEnabled || !IsVisible)
    02324                 return false;
    02325
    02326             switch(msg)
    02327             {
    02328                 case NativeMethods.WindowMessage.KeyDown:
    02329                     if ((System.Windows.Forms.Keys)wParam.ToInt32() == System.Windows.Forms.Keys.Space)
    02330                     {
    02331                         isPressed = true;
    02332                         return true;
    02333                     }
    02334                     break;
    02335                 case NativeMethods.WindowMessage.KeyUp:
    02336                     if ((System.Windows.Forms.Keys)wParam.ToInt32() == System.Windows.Forms.Keys.Space)
    02337                     {
    02338                         if (isPressed)
    02339                         {
    02340                             isPressed = false;
    02341                             SetCheckedInternal(!isBoxChecked, true);
    02342                         }
    02343                         return true;
    02344                     }
    02345                     break;
    02346             }
    02347             return false;
    02348         }
    02349
    02353         public override bool HandleMouse(NativeMethods.WindowMessage msg, System.Drawing.Point pt, IntPtr wParam, IntPtr lParam)
    02354         {
    02355             if (!IsEnabled || !IsVisible)
    02356                 return false;
    02357
    02358             switch(msg)
    02359             {
    02360                 case NativeMethods.WindowMessage.LeftButtonDoubleClick:
    02361                 case NativeMethods.WindowMessage.LeftButtonDown:
    02362                 {
    02363                     if (ContainsPoint(pt))
    02364                     {
    02365                         // Pressed while inside the control
    02366                         isPressed = true;
    02367                         Parent.SampleFramework.Window.Capture = true;
    02368                         if ( (!hasFocus) && (parentDialog.IsUsingKeyboardInput) )
    02369                             Dialog.RequestFocus(this);
    02370
    02371                         return true;
    02372                     }
    02373                 }
    02374                     break;
    02375                 case NativeMethods.WindowMessage.LeftButtonUp:
    02376                 {
    02377                     if (isPressed)
    02378                     {
    02379                         isPressed = false;
    02380                         Parent.SampleFramework.Window.Capture = false;
    02381
    02382                         // Button click
    02383                         if (ContainsPoint(pt))
    02384                         {
    02385                             SetCheckedInternal(!isBoxChecked, true);
    02386                         }
    02387
    02388                         return true;
    02389                     }
    02390                 }
    02391                     break;
    02392             }
    02393
    02394             return false;
    02395         }
    02396     }
    02397     #endregion
    02398
    02399     #region RadioButton Control
    02403     public class RadioButton : Checkbox
    02404     {
    02405         protected uint buttonGroupIndex;
    02409         public RadioButton(Dialog parent) : base(parent)
    02410         {
    02411             controlType = ControlType.RadioButton;
    02412             parentDialog = parent;
    02413         }
    02414
    02418         public uint ButtonGroup
    02419         {
    02420             get { return buttonGroupIndex; }
    02421             set { buttonGroupIndex = value; }
    02422         }
    02423
    02427         public void SetChecked(bool ischecked, bool clear)
    02428         {
    02429             SetCheckedInternal(ischecked, clear, false);
    02430         }
    02431
    02435         protected virtual void SetCheckedInternal(bool ischecked, bool clearGroup, bool fromInput)
    02436         {
    02437             isBoxChecked = ischecked;
    02438             RaiseChangedEvent(this, fromInput);
    02439         }
    02440
    02444         public override void OnHotKey()
    02445         {
    02446             SetCheckedInternal(true, true);
    02447         }
    02448
    02452         public override bool HandleKeyboard(NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
    02453         {
    02454             if (!IsEnabled || !IsVisible)
    02455                 return false;
    02456
    02457             switch(msg)
    02458             {
    02459                 case NativeMethods.WindowMessage.KeyDown:
    02460                     if ((System.Windows.Forms.Keys)wParam.ToInt32() == System.Windows.Forms.Keys.Space)
    02461                     {
    02462                         isPressed = true;
    02463                         return true;
    02464                     }
    02465                     break;
    02466                 case NativeMethods.WindowMessage.KeyUp:
    02467                     if ((System.Windows.Forms.Keys)wParam.ToInt32() == System.Windows.Forms.Keys.Space)
    02468                     {
    02469                         if (isPressed)
    02470                         {
    02471                             isPressed = false;
    02472                             parentDialog.ClearRadioButtonGroup(buttonGroupIndex);
    02473                             isBoxChecked = !isBoxChecked;
    02474
    02475                             RaiseChangedEvent(this, true);
    02476                         }
    02477                         return true;
    02478                     }
    02479                     break;
    02480             }
    02481             return false;
    02482         }
    02483
    02487         public override bool HandleMouse(NativeMethods.WindowMessage msg, System.Drawing.Point pt, IntPtr wParam, IntPtr lParam)
    02488         {
    02489             if (!IsEnabled || !IsVisible)
    02490                 return false;
    02491
    02492             switch(msg)
    02493             {
    02494                 case NativeMethods.WindowMessage.LeftButtonDoubleClick:
    02495                 case NativeMethods.WindowMessage.LeftButtonDown:
    02496                 {
    02497                     if (ContainsPoint(pt))
    02498                     {
    02499                         // Pressed while inside the control
    02500                         isPressed = true;
    02501                         Parent.SampleFramework.Window.Capture = true;
    02502                         if ( (!hasFocus) && (parentDialog.IsUsingKeyboardInput) )
    02503                             Dialog.RequestFocus(this);
    02504
    02505                         return true;
    02506                     }
    02507                 }
    02508                     break;
    02509                 case NativeMethods.WindowMessage.LeftButtonUp:
    02510                 {
    02511                     if (isPressed)
    02512                     {
    02513                         isPressed = false;
    02514                         Parent.SampleFramework.Window.Capture = false;
    02515
    02516                         // Button click
    02517                         if (ContainsPoint(pt))
    02518                         {
    02519                             parentDialog.ClearRadioButtonGroup(buttonGroupIndex);
    02520                             isBoxChecked = !isBoxChecked;
    02521
    02522                             RaiseChangedEvent(this, true);
    02523                         }
    02524
    02525                         return true;
    02526                     }
    02527                 }
    02528                     break;
    02529             }
    02530
    02531             return false;
    02532         }
    02533     }
    02534     #endregion
    02535
    02536     #region Scrollbar control
    02540     public class ScrollBar : Control
    02541     {
    02542         public const int TrackLayer = 0;
    02543         public const int UpButtonLayer = 1;
    02544         public const int DownButtonLayer = 2;
    02545         public const int ThumbLayer = 3;
    02546         protected const int MinimumThumbSize = 8;
    02547         #region Instance Data
    02548         protected bool showingThumb;
    02549         protected System.Drawing.Rectangle upButtonRect;
    02550         protected System.Drawing.Rectangle downButtonRect;
    02551         protected System.Drawing.Rectangle trackRect;
    02552         protected System.Drawing.Rectangle thumbRect;
    02553         protected int position; // Position of the first displayed item
    02554         protected int pageSize; // How many items are displayable in one page
    02555         protected int start; // First item
    02556         protected int end; // The index after the last item
    02557         private int thumbOffsetY;
    02558         private bool isDragging;
    02559         #endregion
    02560
    02564         public ScrollBar(Dialog parent) : base(parent)
    02565         {
    02566             // Store parent and control type
    02567             controlType = ControlType.Scrollbar;
    02568             parentDialog = parent;
    02569
    02570             // Set default properties
    02571             showingThumb = true;
    02572             upButtonRect = System.Drawing.Rectangle.Empty;
    02573             downButtonRect = System.Drawing.Rectangle.Empty;
    02574             trackRect = System.Drawing.Rectangle.Empty;
    02575             thumbRect = System.Drawing.Rectangle.Empty;
    02576
    02577             position = 0;
    02578             pageSize = 1;
    02579             start = 0;
    02580             end = 1;
    02581         }
    02582
    02586         protected override void UpdateRectangles()
    02587         {
    02588             // Get the bounding box first
    02589             base.UpdateRectangles();
    02590
    02591             // Make sure buttons are square
    02592             upButtonRect = new System.Drawing.Rectangle(boundingBox.Location,
    02593                 new System.Drawing.Size(boundingBox.Width, boundingBox.Width));
    02594
    02595             downButtonRect = new System.Drawing.Rectangle(boundingBox.Left, boundingBox.Bottom - boundingBox.Width,
    02596                 boundingBox.Width, boundingBox.Width);
    02597
    02598             trackRect = new System.Drawing.Rectangle(upButtonRect.Left, upButtonRect.Bottom,
    02599                 upButtonRect.Width, downButtonRect.Top - upButtonRect.Bottom);
    02600
    02601             thumbRect = upButtonRect;
    02602
    02603             UpdateThumbRectangle();
    02604         }
    02605
    02609         public int TrackPosition
    02610         {
    02611             get { return position; }
    02612             set { position = value; Cap(); UpdateThumbRectangle(); }
    02613         }
    02617         public int PageSize
    02618         {
    02619             get { return pageSize; }
    02620             set { pageSize = value; Cap(); UpdateThumbRectangle(); }
    02621         }
    02622
    02624         protected void Cap()
    02625         {
    02626             if (position < start || end - start <= pageSize)
    02627             {
    02628                 position = start;
    02629             }
    02630             else if (position + pageSize > end)
    02631                 position = end - pageSize;
    02632         }
    02633
    02635         protected void UpdateThumbRectangle()
    02636         {
    02637             if (end - start > pageSize)
    02638             {
    02639                 int thumbHeight = Math.Max(trackRect.Height * pageSize / (end-start), MinimumThumbSize);
    02640                 int maxPosition = end - start - pageSize;
    02641                 thumbRect.Location = new System.Drawing.Point(thumbRect.Left,
    02642                     trackRect.Top + (position - start) * (trackRect.Height - thumbHeight) / maxPosition);
    02643                 thumbRect.Size = new System.Drawing.Size(thumbRect.Width, thumbHeight);
    02644                 showingThumb = true;
    02645             }
    02646             else
    02647             {
    02648                 // No content to scroll
    02649                 thumbRect.Height = 0;
    02650                 showingThumb = false;
    02651             }
    02652         }
    02653
    02655         public void Scroll(int delta)
    02656         {
    02657             // Perform scroll
    02658             position += delta;
    02659             // Cap position
    02660             Cap();
    02661             // Update thumb rectangle
    02662             UpdateThumbRectangle();
    02663         }
    02664
    02666         public void ShowItem(int index)
    02667         {
    02668             // Cap the index
    02669             if (index < 0)
    02670                 index = 0;
    02671
    02672             if (index >= end)
    02673                 index = end - 1;
    02674
    02675             // Adjust the position to show this item
    02676             if (position > index)
    02677                 position = index;
    02678             else if (position + pageSize <= index)
    02679                 position = index - pageSize + 1;
    02680
    02681             // Update thumbs again
    02682             UpdateThumbRectangle();
    02683         }
    02684
    02686         public void SetTrackRange(int startRange, int endRange)
    02687         {
    02688             start = startRange; end = endRange;
    02689             Cap();
    02690             UpdateThumbRectangle();
    02691         }
    02692
    02694         public override void Render(Device device, float elapsedTime)
    02695         {
    02696             ControlState state = ControlState.Normal;
    02697             if (IsVisible == false)
    02698                 state = ControlState.Hidden;
    02699             else if ( (IsEnabled == false) || (showingThumb == false) )
    02700                 state = ControlState.Disabled;
    02701             else if (isMouseOver)
    02702                 state = ControlState.MouseOver;
    02703             else if (hasFocus)
    02704                 state = ControlState.Focus;
    02705
    02706             float blendRate = (state == ControlState.Pressed) ? 0.0f : 0.8f;
    02707
    02708             // Background track layer
    02709             Element e = elementList[ScrollBar.TrackLayer] as Element;
    02710
    02711             // Blend current color
    02712             e.TextureColor.Blend(state, elapsedTime, blendRate);
    02713             parentDialog.DrawSprite(e, trackRect);
    02714
    02715             // Up arrow
    02716             e = elementList[ScrollBar.UpButtonLayer] as Element;
    02717             e.TextureColor.Blend(state, elapsedTime, blendRate);
    02718             parentDialog.DrawSprite(e, upButtonRect);
    02719
    02720             // Down arrow
    02721             e = elementList[ScrollBar.DownButtonLayer] as Element;
    02722             e.TextureColor.Blend(state, elapsedTime, blendRate);
    02723             parentDialog.DrawSprite(e, downButtonRect);
    02724
    02725             // Thumb button
    02726             e = elementList[ScrollBar.ThumbLayer] as Element;
    02727             e.TextureColor.Blend(state, elapsedTime, blendRate);
    02728             parentDialog.DrawSprite(e, thumbRect);
    02729         }
    02730
    02732         public override bool HandleMouse(NativeMethods.WindowMessage msg, System.Drawing.Point pt, IntPtr wParam, IntPtr lParam)
    02733         {
    02734             if (!IsEnabled || !IsVisible)
    02735                 return false;
    02736
    02737             switch(msg)
    02738             {
    02739                 case NativeMethods.WindowMessage.LeftButtonDoubleClick:
    02740                 case NativeMethods.WindowMessage.LeftButtonDown:
    02741                 {
    02742                     Parent.SampleFramework.Window.Capture = true;
    02743
    02744                     // Check for on up button
    02745                     if (upButtonRect.Contains(pt))
    02746                     {
    02747                         if (position > start)
    02748                             --position;
    02749                         UpdateThumbRectangle();
    02750                         return true;
    02751                     }
    02752
    02753                     // Check for on down button
    02754                     if (downButtonRect.Contains(pt))
    02755                     {
    02756                         if (position + pageSize < end)
    02757                             ++position;
    02758                         UpdateThumbRectangle();
    02759                         return true;
    02760                     }
    02761
    02762                     // Check for click on thumb
    02763                     if (thumbRect.Contains(pt))
    02764                     {
    02765                         isDragging = true;
    02766                         thumbOffsetY = pt.Y - thumbRect.Top;
    02767                         return true;
    02768                     }
    02769
    02770                     // check for click on track
    02771                     if (thumbRect.Left <= pt.X &&
    02772                         thumbRect.Right > pt.X)
    02773                     {
    02774                         if (thumbRect.Top > pt.Y &&
    02775                             trackRect.Top <= pt.Y)
    02776                         {
    02777                             Scroll(-(pageSize-1));
    02778                             return true;
    02779                         }
    02780                         else if (thumbRect.Bottom <= pt.Y &&
    02781                             trackRect.Bottom > pt.Y)
    02782                         {
    02783                             Scroll(pageSize-1);
    02784                             return true;
    02785                         }
    02786                     }
    02787
    02788                     break;
    02789                 }
    02790                 case NativeMethods.WindowMessage.LeftButtonUp:
    02791                 {
    02792                     isDragging = false;
    02793                     Parent.SampleFramework.Window.Capture = false;
    02794                     UpdateThumbRectangle();
    02795                     break;
    02796                 }
    02797
    02798                 case NativeMethods.WindowMessage.MouseMove:
    02799                 {
    02800                     if (isDragging)
    02801                     {
    02802                         // Calculate new bottom and top of thumb rect
    02803                         int bottom = thumbRect.Bottom + (pt.Y - thumbOffsetY - thumbRect.Top);
    02804                         int top = pt.Y - thumbOffsetY;
    02805                         thumbRect = new System.Drawing.Rectangle(thumbRect.Left, top, thumbRect.Width, bottom - top);
    02806                         if (thumbRect.Top < trackRect.Top)
    02807                             thumbRect.Offset(0, trackRect.Top - thumbRect.Top);
    02808                         else if (thumbRect.Bottom > trackRect.Bottom)
    02809                             thumbRect.Offset(0, trackRect.Bottom - thumbRect.Bottom);
    02810
    02811                         // Compute first item index based on thumb position
    02812                         int maxFirstItem = end - start - pageSize; // Largest possible index for first item
    02813                         int maxThumb = trackRect.Height - thumbRect.Height; // Largest possible thumb position
    02814
    02815                         position = start + (thumbRect.Top - trackRect.Top +
    02816                             maxThumb / (maxFirstItem * 2) ) * // Shift by half a row to avoid last row covered
    02817                             maxFirstItem / maxThumb;
    02818
    02819                         return true;
    02820                     }
    02821                     break;
    02822                 }
    02823             }
    02824
    02825             // Was not handled
    02826             return false;
    02827         }
    02828
    02829     }
    02830     #endregion
    02831
    02832     #region ComboBox Control
    02834     public struct ComboBoxItem
    02835     {
    02836         public string ItemText;
    02837         public object ItemData;
    02838         public System.Drawing.Rectangle ItemRect;
    02839         public bool IsItemVisible;
    02840     }
    02841
    02843     public class ComboBox : Button
    02844     {
    02845         public const int MainLayer = 0;
    02846         public const int ComboButtonLayer = 1;
    02847         public const int DropdownLayer = 2;
    02848         public const int SelectionLayer = 3;
    02849         #region Event code
    02850         public event EventHandler Changed;
    02852         protected void RaiseChangedEvent(ComboBox sender, bool wasTriggeredByUser)
    02853         {
    02854             // Discard events triggered programatically if these types of events haven't been
    02855             // enabled
    02856             if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
    02857                 return;
    02858
    02859             // Fire both the changed and clicked event
    02860             base.RaiseClickEvent(sender, wasTriggeredByUser);
    02861             if (Changed != null)
    02862                 Changed(sender, EventArgs.Empty);
    02863         }
    02864         #endregion
    02865         private bool isScrollBarInit;
    02866
    02867         #region Instance data
    02868         protected int selectedIndex;
    02869         protected int focusedIndex;
    02870         protected int dropHeight;
    02871         protected ScrollBar scrollbarControl;
    02872         protected int scrollWidth;
    02873         protected bool isComboOpen;
    02874         protected System.Drawing.Rectangle textRect;
    02875         protected System.Drawing.Rectangle buttonRect;
    02876         protected System.Drawing.Rectangle dropDownRect;
    02877         protected System.Drawing.Rectangle dropDownTextRect;
    02878         protected ArrayList itemList;
    02879         #endregion
    02880
    02882         public ComboBox(Dialog parent) : base(parent)
    02883         {
    02884             // Store control type and parent dialog
    02885             controlType = ControlType.ComboBox;
    02886             parentDialog = parent;
    02887             // Create the scrollbar control too
    02888             scrollbarControl = new ScrollBar(parent);
    02889
    02890             // Set some default items
    02891             dropHeight = 100;
    02892             scrollWidth = 16;
    02893             selectedIndex = -1;
    02894             focusedIndex = -1;
    02895             isScrollBarInit = false;
    02896
    02897             // Create the item list array
    02898             itemList = new ArrayList();
    02899         }
    02900
    02902         protected override void UpdateRectangles()
    02903         {
    02904             // Get bounding box
    02905             base.UpdateRectangles();
    02906
    02907             // Update the bounding box for the items
    02908             buttonRect = new System.Drawing.Rectangle(boundingBox.Right - boundingBox.Height, boundingBox.Top,
    02909                 boundingBox.Height, boundingBox.Height);
    02910
    02911             textRect = boundingBox;
    02912             textRect.Size = new System.Drawing.Size(textRect.Width - buttonRect.Width, textRect.Height);
    02913
    02914             dropDownRect = textRect;
    02915             dropDownRect.Offset(0, (int)(0.9f * textRect.Height));
    02916             dropDownRect.Size = new System.Drawing.Size(dropDownRect.Width - scrollWidth, dropDownRect.Height + dropHeight);
    02917
    02918             // Scale it down slightly
    02919             System.Drawing.Point loc = dropDownRect.Location;
    02920             System.Drawing.Size size = dropDownRect.Size;
    02921
    02922             loc.X += (int)(0.1f * dropDownRect.Width);
    02923             loc.Y += (int)(0.1f * dropDownRect.Height);
    02924             size.Width -= (2 * (int)(0.1f * dropDownRect.Width));
    02925             size.Height -= (2 * (int)(0.1f * dropDownRect.Height));
    02926
    02927             dropDownTextRect = new System.Drawing.Rectangle(loc, size);
    02928
    02929             // Update the scroll bars rects too
    02930             scrollbarControl.SetLocation(dropDownRect.Right, dropDownRect.Top + 2);
    02931             scrollbarControl.SetSize(scrollWidth, dropDownRect.Height - 2);
    02932             FontNode fNode = DialogResourceManager.GetGlobalInstance().GetFontNode((int)(elementList[2] as Element).FontIndex);
    02933             if ((fNode != null) && (fNode.Height > 0))
    02934             {
    02935                 scrollbarControl.PageSize = (int)(dropDownTextRect.Height / fNode.Height);
    02936
    02937                 // The selected item may have been scrolled off the page.
    02938                 // Ensure that it is in page again.
    02939                 scrollbarControl.ShowItem(selectedIndex);
    02940             }
    02941         }
    02942
    02944         public void SetDropHeight(int height) { dropHeight = height; UpdateRectangles(); }
    02946         public void SetScrollbarWidth(int width) { scrollWidth = width; UpdateRectangles(); }
    02948         public override bool CanHaveFocus { get { return (IsVisible && IsEnabled); } }
    02950         public int NumberItems { get { return itemList.Count; } }
    02952         public ComboBoxItem this[int index]
    02953         {
    02954             get { return (ComboBoxItem)itemList[index]; }
    02955         }
    02956
    02958         public override void OnInitialize()
    02959         {
    02960             parentDialog.InitializeControl(scrollbarControl);
    02961         }
    02962
    02964         public override void OnFocusOut()
    02965         {
    02966             // Call base first
    02967             base.OnFocusOut ();
    02968             isComboOpen = false;
    02969         }
    02971         public override void OnHotKey()
    02972         {
    02973             if (isComboOpen)
    02974                 return; // Nothing to do yet
    02975
    02976             if (selectedIndex == -1)
    02977                 return; // Nothing selected
    02978
    02979             selectedIndex++;
    02980             if (selectedIndex >= itemList.Count)
    02981                 selectedIndex = 0;
    02982
    02983             focusedIndex = selectedIndex;
    02984             RaiseChangedEvent(this, true);
    02985         }
    02986
    02987
    02989         public override bool HandleKeyboard(NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
    02990         {
    02991             const uint RepeatMask = (0x40000000);
    02992
    02993             if (!IsEnabled || !IsVisible)
    02994                 return false;
    02995
    02996             // Let the scroll bar have a chance to handle it first
    02997             if (scrollbarControl.HandleKeyboard(msg, wParam, lParam))
    02998                 return true;
    02999
    03000             switch (msg)
    03001             {
    03002                 case NativeMethods.WindowMessage.KeyDown:
    03003                 {
    03004                     switch((System.Windows.Forms.Keys)wParam.ToInt32())
    03005                     {
    03006                         case System.Windows.Forms.Keys.Return:
    03007                         {
    03008                             if (isComboOpen)
    03009                             {
    03010                                 if (selectedIndex != focusedIndex)
    03011                                 {
    03012                                     selectedIndex = focusedIndex;
    03013                                     RaiseChangedEvent(this, true);
    03014                                 }
    03015                                 isComboOpen = false;
    03016
    03017                                 if (!Parent.IsUsingKeyboardInput)
    03018                                     Dialog.ClearFocus();
    03019
    03020                                 return true;
    03021                             }
    03022                             break;
    03023                         }
    03024                         case System.Windows.Forms.Keys.F4:
    03025                         {
    03026                             // Filter out auto repeats
    03027                             if ((lParam.ToInt32() & RepeatMask) != 0)
    03028                                 return true;
    03029
    03030                             isComboOpen = !isComboOpen;
    03031                             if (!isComboOpen)
    03032                             {
    03033                                 RaiseChangedEvent(this, true);
    03034
    03035                                 if (!Parent.IsUsingKeyboardInput)
    03036                                     Dialog.ClearFocus();
    03037                             }
    03038
    03039                             return true;
    03040                         }
    03041                         case System.Windows.Forms.Keys.Left:
    03042                         case System.Windows.Forms.Keys.Up:
    03043                         {
    03044                             if (focusedIndex > 0)
    03045                             {
    03046                                 focusedIndex--;
    03047                                 selectedIndex = focusedIndex;
    03048                                 if (!isComboOpen)
    03049                                     RaiseChangedEvent(this, true);
    03050                             }
    03051                             return true;
    03052                         }
    03053                         case System.Windows.Forms.Keys.Right:
    03054                         case System.Windows.Forms.Keys.Down:
    03055                         {
    03056                             if (focusedIndex + 1 < (int)NumberItems)
    03057                             {
    03058                                 focusedIndex++;
    03059                                 selectedIndex = focusedIndex;
    03060                                 if (!isComboOpen)
    03061                                     RaiseChangedEvent(this, true);
    03062                             }
    03063                             return true;
    03064                         }
    03065                     }
    03066                     break;
    03067                 }
    03068             }
    03069
    03070             return false;
    03071         }
    03072
    03074         public override bool HandleMouse(NativeMethods.WindowMessage msg, System.Drawing.Point pt, IntPtr wParam, IntPtr lParam)
    03075         {
    03076             if (!IsEnabled || !IsVisible)
    03077                 return false; // Nothing to do
    03078
    03079             // Let the scroll bar handle it first
    03080             if (scrollbarControl.HandleMouse(msg, pt, wParam, lParam))
    03081                 return true;
    03082
    03083             // Ok, scrollbar didn't handle it, move on
    03084             switch(msg)
    03085             {
    03086                 case NativeMethods.WindowMessage.MouseMove:
    03087                 {
    03088                     if (isComboOpen && dropDownRect.Contains(pt))
    03089                     {
    03090                         // Determine which item has been selected
    03091                         for (int i = 0; i < itemList.Count; i++)
    03092                         {
    03093                             ComboBoxItem cbi = (ComboBoxItem)itemList[i];
    03094                             if (cbi.IsItemVisible && cbi.ItemRect.Contains(pt))
    03095                             {
    03096                                 focusedIndex = i;
    03097                             }
    03098                         }
    03099                         return true;
    03100                     }
    03101                     break;
    03102                 }
    03103                 case NativeMethods.WindowMessage.LeftButtonDoubleClick:
    03104                 case NativeMethods.WindowMessage.LeftButtonDown:
    03105                 {
    03106                     if (ContainsPoint(pt))
    03107                     {
    03108                         // Pressed while inside the control
    03109                         isPressed = true;
    03110                         Parent.SampleFramework.Window.Capture = true;
    03111
    03112                         if (!hasFocus)
    03113                             Dialog.RequestFocus(this);
    03114
    03115                         // Toggle dropdown
    03116                         if (hasFocus)
    03117                         {
    03118                             isComboOpen = !isComboOpen;
    03119                             if (!isComboOpen)
    03120                             {
    03121                                 if (!parentDialog.IsUsingKeyboardInput)
    03122                                     Dialog.ClearFocus();
    03123                             }
    03124                         }
    03125
    03126                         return true;
    03127                     }
    03128
    03129                     // Perhaps this click is within the dropdown
    03130                     if (isComboOpen && dropDownRect.Contains(pt))
    03131                     {
    03132                         // Determine which item has been selected
    03133                         for (int i = scrollbarControl.TrackPosition; i < itemList.Count; i++)
    03134                         {
    03135                             ComboBoxItem cbi = (ComboBoxItem)itemList[i];
    03136                             if (cbi.IsItemVisible && cbi.ItemRect.Contains(pt))
    03137                             {
    03138                                 selectedIndex = focusedIndex = i;
    03139                                 RaiseChangedEvent(this, true);
    03140
    03141                                 isComboOpen = false;
    03142
    03143                                 if (!parentDialog.IsUsingKeyboardInput)
    03144                                     Dialog.ClearFocus();
    03145
    03146                                 break;
    03147                             }
    03148                         }
    03149                         return true;
    03150                     }
    03151                     // Mouse click not on main control or in dropdown, fire an event if needed
    03152                     if (isComboOpen)
    03153                     {
    03154                         focusedIndex = selectedIndex;
    03155                         RaiseChangedEvent(this, true);
    03156                         isComboOpen = false;
    03157                     }
    03158
    03159                     // Make sure the control is no longer 'pressed'
    03160                     isPressed = false;
    03161
    03162                     // Release focus if appropriate
    03163                     if (!parentDialog.IsUsingKeyboardInput)
    03164                         Dialog.ClearFocus();
    03165
    03166                     break;
    03167                 }
    03168                 case NativeMethods.WindowMessage.LeftButtonUp:
    03169                 {
    03170                     if (isPressed && ContainsPoint(pt))
    03171                     {
    03172                         // Button click
    03173                         isPressed = false;
    03174                         Parent.SampleFramework.Window.Capture = false;
    03175                         return true;
    03176                     }
    03177                     break;
    03178                 }
    03179                 case NativeMethods.WindowMessage.MouseWheel:
    03180                 {
    03181                     int zdelta = (short)NativeMethods.HiWord((uint)wParam.ToInt32()) / Dialog.WheelDelta;
    03182                     if (isComboOpen)
    03183                     {
    03184                         scrollbarControl.Scroll(-zdelta * System.Windows.Forms.SystemInformation.MouseWheelScrollLines);
    03185                     }
    03186                     else
    03187                     {
    03188                         if (zdelta > 0)
    03189                         {
    03190                             if (focusedIndex > 0)
    03191                             {
    03192                                 focusedIndex--;
    03193                                 selectedIndex = focusedIndex;
    03194                                 if (!isComboOpen)
    03195                                 {
    03196                                     RaiseChangedEvent(this, true);
    03197                                 }
    03198                             }
    03199                         }
    03200                         else
    03201                         {
    03202                             if (focusedIndex +1 < NumberItems)
    03203                             {
    03204                                 focusedIndex++;
    03205                                 selectedIndex = focusedIndex;
    03206                                 if (!isComboOpen)
    03207                                 {
    03208                                     RaiseChangedEvent(this, true);
    03209                                 }
    03210                             }
    03211                         }
    03212                     }
    03213                     return true;
    03214                 }
    03215             }
    03216
    03217             // Didn't handle it
    03218             return false;
    03219         }
    03220
    03222         public override void Render(Device device, float elapsedTime)
    03223         {
    03224             ControlState state = ControlState.Normal;
    03225             if (!isComboOpen)
    03226                 state = ControlState.Hidden;
    03227
    03228             // Dropdown box
    03229             Element e = elementList[ComboBox.DropdownLayer] as Element;
    03230
    03231             // If we have not initialized the scroll bar page size,
    03232             // do that now.
    03233             if (!isScrollBarInit)
    03234             {
    03235                 FontNode fNode = DialogResourceManager.GetGlobalInstance().GetFontNode((int)e.FontIndex);
    03236                 if ((fNode != null) && (fNode.Height > 0))
    03237                     scrollbarControl.PageSize = (int)(dropDownTextRect.Height / fNode.Height);
    03238                 else
    03239                     scrollbarControl.PageSize = dropDownTextRect.Height;
    03240
    03241                 isScrollBarInit = true;
    03242             }
    03243
    03244             if (isComboOpen)
    03245                 scrollbarControl.Render(device, elapsedTime);
    03246
    03247             // Blend current color
    03248             e.TextureColor.Blend(state, elapsedTime);
    03249             e.FontColor.Blend(state, elapsedTime);
    03250             parentDialog.DrawSprite(e, dropDownRect);
    03251
    03252             // Selection outline
    03253             Element selectionElement = elementList[ComboBox.SelectionLayer] as Element;
    03254             selectionElement.TextureColor.Current = e.TextureColor.Current;
    03255             selectionElement.FontColor.Current = selectionElement.FontColor.States[(int)ControlState.Normal];
    03256
    03257             FontNode font = DialogResourceManager.GetGlobalInstance().GetFontNode((int)e.FontIndex);
    03258             int currentY = dropDownTextRect.Top;
    03259             int remainingHeight = dropDownTextRect.Height;
    03260
    03261             for (int i = scrollbarControl.TrackPosition; i < itemList.Count; i++)
    03262             {
    03263                 ComboBoxItem cbi = (ComboBoxItem)itemList[i];
    03264
    03265                 // Make sure there's room left in the dropdown
    03266                 remainingHeight -= (int)font.Height;
    03267                 if (remainingHeight < 0)
    03268                 {
    03269                     // Not visible, store that item
    03270                     cbi.IsItemVisible = false;
    03271                     itemList[i] = cbi; // Store this back in list
    03272                     continue;
    03273                 }
    03274
    03275                 cbi.ItemRect = new System.Drawing.Rectangle(dropDownTextRect.Left, currentY,
    03276                     dropDownTextRect.Width, (int)font.Height);
    03277                 cbi.IsItemVisible = true;
    03278                 currentY += (int)font.Height;
    03279                 itemList[i] = cbi; // Store this back in list
    03280
    03281                 if (isComboOpen)
    03282                 {
    03283                     if (focusedIndex == i)
    03284                     {
    03285                         System.Drawing.Rectangle rect = new System.Drawing.Rectangle(
    03286                             dropDownRect.Left, cbi.ItemRect.Top - 2, dropDownRect.Width,
    03287                             cbi.ItemRect.Height + 4);
    03288                         parentDialog.DrawSprite(selectionElement, rect);
    03289                         parentDialog.DrawText(cbi.ItemText, selectionElement, cbi.ItemRect);
    03290                     }
    03291                     else
    03292                     {
    03293                         parentDialog.DrawText(cbi.ItemText, e, cbi.ItemRect);
    03294                     }
    03295                 }
    03296             }
    03297
    03298             int offsetX = 0;
    03299             int offsetY = 0;
    03300
    03301             state = ControlState.Normal;
    03302             if (IsVisible == false)
    03303                 state = ControlState.Hidden;
    03304             else if (IsEnabled == false)
    03305                 state = ControlState.Disabled;
    03306             else if (isPressed)
    03307             {
    03308                 state = ControlState.Pressed;
    03309                 offsetX = 1;
    03310                 offsetY = 2;
    03311             }
    03312             else if (isMouseOver)
    03313             {
    03314                 state = ControlState.MouseOver;
    03315                 offsetX = -1;
    03316                 offsetY = -2;
    03317             }
    03318             else if (hasFocus)
    03319                 state = ControlState.Focus;
    03320
    03321             float blendRate = (state == ControlState.Pressed) ? 0.0f : 0.8f;
    03322
    03323             // Button
    03324             e = elementList[ComboBox.ComboButtonLayer] as Element;
    03325
    03326             // Blend current color
    03327             e.TextureColor.Blend(state, elapsedTime, blendRate);
    03328
    03329             System.Drawing.Rectangle windowRect = buttonRect;
    03330             windowRect.Offset(offsetX, offsetY);
    03331             // Draw sprite
    03332             parentDialog.DrawSprite(e, windowRect);
    03333
    03334             if (isComboOpen)
    03335                 state = ControlState.Pressed;
    03336
    03337             // Main text box
    03338             e = elementList[ComboBox.MainLayer] as Element;
    03339
    03340             // Blend current color
    03341             e.TextureColor.Blend(state, elapsedTime, blendRate);
    03342             e.FontColor.Blend(state, elapsedTime, blendRate);
    03343
    03344             // Draw sprite
    03345             parentDialog.DrawSprite(e, textRect);
    03346
    03347             if (selectedIndex >= 0 && selectedIndex < itemList.Count)
    03348             {
    03349                 try
    03350                 {
    03351                     ComboBoxItem cbi = (ComboBoxItem)itemList[selectedIndex];
    03352                     parentDialog.DrawText(cbi.ItemText, e, textRect);
    03353                 }
    03354                 catch {} // Ignore
    03355             }
    03356
    03357         }
    03358
    03359         #region Item Controlling methods
    03361         public void AddItem(string text, object data)
    03362         {
    03363             if ((text == null) || (text.Length == 0))
    03364                 throw new ArgumentNullException("text", "You must pass in a valid item name when adding a new item.");
    03365
    03366             // Create a new item and add it
    03367             ComboBoxItem newitem = new ComboBoxItem();
    03368             newitem.ItemText = text;
    03369             newitem.ItemData = data;
    03370             itemList.Add(newitem);
    03371
    03372             // Update the scrollbar with the new range
    03373             scrollbarControl.SetTrackRange(0, itemList.Count);
    03374
    03375             // If this is the only item in the list, it should be selected
    03376             if (NumberItems == 1)
    03377             {
    03378                 selectedIndex = 0;
    03379                 focusedIndex = 0;
    03380                 RaiseChangedEvent(this, false);
    03381             }
    03382         }
    03383
    03385         public void RemoveAt(int index)
    03386         {
    03387             // Remove the item
    03388             itemList.RemoveAt(index);
    03389
    03390             // Update the scrollbar with the new range
    03391             scrollbarControl.SetTrackRange(0, itemList.Count);
    03392
    03393             if (selectedIndex >= itemList.Count)
    03394                 selectedIndex = itemList.Count - 1;
    03395         }
    03396
    03398         public void Clear()
    03399         {
    03400             // clear the list
    03401             itemList.Clear();
    03402
    03403             // Update scroll bar and index
    03404             scrollbarControl.SetTrackRange(0, 1);
    03405             focusedIndex = selectedIndex = -1;
    03406         }
    03407
    03409         public bool ContainsItem(string text, int start)
    03410         {
    03411             return (FindItem(text, start) != -1);
    03412         }
    03414         public bool ContainsItem(string text) { return ContainsItem(text, 0); }
    03415
    03417         public object GetSelectedData()
    03418         {
    03419             if (selectedIndex < 0)
    03420                 return null; // Nothing selected
    03421
    03422             ComboBoxItem cbi = (ComboBoxItem)itemList[selectedIndex];
    03423             return cbi.ItemData;
    03424         }
    03425
    03427         public ComboBoxItem GetSelectedItem()
    03428         {
    03429             if (selectedIndex < 0)
    03430                 throw new ArgumentOutOfRangeException("selectedIndex", "No item selected.");
    03431
    03432             return (ComboBoxItem)itemList[selectedIndex];
    03433         }
    03434
    03436         public object GetItemData(string text)
    03437         {
    03438             int index = FindItem(text);
    03439             if (index == -1)
    03440                 return null; // no item
    03441
    03442             ComboBoxItem cbi = (ComboBoxItem)itemList[index];
    03443             return cbi.ItemData;
    03444         }
    03445
    03447         protected int FindItem(string text, int start)
    03448         {
    03449             if ((text == null) || (text.Length == 0))
    03450                 return -1;
    03451
    03452             for(int i = start; i < itemList.Count; i++)
    03453             {
    03454                 ComboBoxItem cbi = (ComboBoxItem)itemList[i];
    03455                 if (string.Compare(cbi.ItemText, text, true) == 0)
    03456                 {
    03457                     return i;
    03458                 }
    03459             }
    03460
    03461             // Never found it
    03462             return -1;
    03463         }
    03465         protected int FindItem(string text) { return FindItem(text, 0); }
    03466
    03468         public void SetSelected(int index)
    03469         {
    03470             if (index >= NumberItems)
    03471                 throw new ArgumentOutOfRangeException("index", "There are not enough items in the list to select this index.");
    03472
    03473             focusedIndex = selectedIndex = index;
    03474             RaiseChangedEvent(this, false);
    03475         }
    03476
    03478         public void SetSelected(string text)
    03479         {
    03480             if ((text == null) || (text.Length == 0))
    03481                 throw new ArgumentNullException("text", "You must pass in a valid item name when adding a new item.");
    03482
    03483             int index = FindItem(text);
    03484             if (index == -1)
    03485                 throw new InvalidOperationException("This item could not be found.");
    03486
    03487             focusedIndex = selectedIndex = index;
    03488             RaiseChangedEvent(this, false);
    03489         }
    03490
    03492         public void SetSelectedByData(object data)
    03493         {
    03494             for (int index = 0; index < itemList.Count; index++)
    03495             {
    03496                 ComboBoxItem cbi = (ComboBoxItem)itemList[index];
    03497                 if (cbi.ItemData.ToString().Equals(data.ToString()))
    03498                 {
    03499                     focusedIndex = selectedIndex = index;
    03500                     RaiseChangedEvent(this, false);
    03501                 }
    03502             }
    03503
    03504             // Could not find this item.  Uncomment line below for debug information
    03505             //System.Diagnostics.Debugger.Log(9,string.Empty, "Could not find an object with this data.\r\n");
    03506         }
    03507
    03508         #endregion
    03509     }
    03510     #endregion
    03511
    03512     #region Slider Control
    03514     public class Slider : Control
    03515     {
    03516         public const int TrackLayer = 0;
    03517         public const int ButtonLayer = 1;
    03518         #region Instance Data
    03519         public event EventHandler ValueChanged;
    03520         protected int currentValue;
    03521         protected int maxValue;
    03522         protected int minValue;
    03523
    03524         protected int dragX; // Mouse position at the start of the drag
    03525         protected int dragOffset; // Drag offset from the center of the button
    03526         protected int buttonX;
    03527
    03528         protected bool isPressed;
    03529         protected System.Drawing.Rectangle buttonRect;
    03530
    03532         public override bool CanHaveFocus { get { return true; }}
    03533
    03535         protected void RaiseValueChanged(Slider sender, bool wasTriggeredByUser)
    03536         {
    03537             // Discard events triggered programatically if these types of events haven't been
    03538             // enabled
    03539             if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
    03540                 return;
    03541
    03542             if (ValueChanged != null)
    03543                 ValueChanged(sender, EventArgs.Empty);
    03544         }
    03546         public int Value { get { return currentValue; } set { SetValueInternal(value, false); } }
    03548         public void SetRange(int min, int max)
    03549         {
    03550             minValue = min;
    03551             maxValue = max;
    03552             SetValueInternal(currentValue, false);
    03553         }
    03554
    03556         protected void SetValueInternal(int newValue, bool fromInput)
    03557         {
    03558             // Clamp to the range
    03559             newValue = Math.Max(minValue, newValue);
    03560             newValue = Math.Min(maxValue, newValue);
    03561             if (newValue == currentValue)
    03562                 return;
    03563
    03564             // Update the value, the rects, then fire the events if necessar
    03565             currentValue = newValue;
    03566             UpdateRectangles();
    03567             RaiseValueChanged(this, fromInput);
    03568         }
    03569         #endregion
    03570
    03572         public Slider(Dialog parent): base(parent)
    03573         {
    03574             controlType = ControlType.Slider;
    03575             parentDialog = parent;
    03576
    03577             isPressed = false;
    03578             minValue = 0;
    03579             maxValue = 100;
    03580             currentValue = 50;
    03581         }
    03582
    03584         public override bool ContainsPoint(System.Drawing.Point pt)
    03585         {
    03586             return boundingBox.Contains(pt) || buttonRect.Contains(pt);
    03587         }
    03588
    03590         protected override void UpdateRectangles()
    03591         {
    03592             // First get the bounding box
    03593             base.UpdateRectangles ();
    03594
    03595             // Create the button rect
    03596             buttonRect = boundingBox;
    03597             buttonRect.Width = buttonRect.Height; // Make it square
    03598
    03599             // Offset it
    03600             buttonRect.Offset(-buttonRect.Width / 2, 0);
    03601             buttonX = (int)((currentValue - minValue) * (float)boundingBox.Width / (maxValue - minValue) );
    03602             buttonRect.Offset(buttonX, 0);
    03603         }
    03604
    03606         public int ValueFromPosition(int x)
    03607         {
    03608             float valuePerPixel = ((float)(maxValue - minValue) / (float)boundingBox.Width);
    03609             return (int)(0.5f + minValue + valuePerPixel * (x - boundingBox.Left));
    03610         }
    03611
    03613         public override bool HandleMouse(Microsoft.Samples.DirectX.UtilityToolkit.NativeMethods.WindowMessage msg, System.Drawing.Point pt, IntPtr wParam, IntPtr lParam)
    03614         {
    03615             if (!IsEnabled || !IsVisible)
    03616                 return false;
    03617
    03618             switch(msg)
    03619             {
    03620                 case NativeMethods.WindowMessage.LeftButtonDoubleClick:
    03621                 case NativeMethods.WindowMessage.LeftButtonDown:
    03622                 {
    03623                     if (buttonRect.Contains(pt))
    03624                     {
    03625                         // Pressed while inside the control
    03626                         isPressed = true;
    03627                         Parent.SampleFramework.Window.Capture = true;
    03628
    03629                         dragX = pt.X;
    03630                         dragOffset = buttonX - dragX;
    03631                         if (!hasFocus)
    03632                             Dialog.RequestFocus(this);
    03633
    03634                         return true;
    03635                     }
    03636                     if (boundingBox.Contains(pt))
    03637                     {
    03638                         if (pt.X > buttonX + controlX)
    03639                         {
    03640                             SetValueInternal(currentValue + 1, true);
    03641                             return true;
    03642                         }
    03643                         if (pt.X < buttonX + controlX)
    03644                         {
    03645                             SetValueInternal(currentValue - 1, true);
    03646                             return true;
    03647                         }
    03648                     }
    03649
    03650                     break;
    03651                 }
    03652                 case NativeMethods.WindowMessage.LeftButtonUp:
    03653                 {
    03654                     if (isPressed)
    03655                     {
    03656                         isPressed = false;
    03657                         Parent.SampleFramework.Window.Capture = false;
    03658                         Dialog.ClearFocus();
    03659                         RaiseValueChanged(this, true);
    03660                         return true;
    03661                     }
    03662                     break;
    03663                 }
    03664                 case NativeMethods.WindowMessage.MouseMove:
    03665                 {
    03666                     if (isPressed)
    03667                     {
    03668                         SetValueInternal(ValueFromPosition(controlX + pt.X + dragOffset), true);
    03669                         return true;
    03670                     }
    03671                     break;
    03672                 }
    03673             }
    03674             return false;
    03675         }
    03676
    03678         public override bool HandleKeyboard(Microsoft.Samples.DirectX.UtilityToolkit.NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
    03679         {
    03680             if (!IsEnabled || !IsVisible)
    03681                 return false;
    03682
    03683             if (msg == NativeMethods.WindowMessage.KeyDown)
    03684             {
    03685                 switch((System.Windows.Forms.Keys)wParam.ToInt32())
    03686                 {
    03687                     case System.Windows.Forms.Keys.Home:
    03688                         SetValueInternal(minValue, true);
    03689                         return true;
    03690                     case System.Windows.Forms.Keys.End:
    03691                         SetValueInternal(maxValue, true);
    03692                         return true;
    03693                     case System.Windows.Forms.Keys.Prior:
    03694                     case System.Windows.Forms.Keys.Left:
    03695                     case System.Windows.Forms.Keys.Up:
    03696                         SetValueInternal(currentValue - 1, true);
    03697                         return true;
    03698                     case System.Windows.Forms.Keys.Next:
    03699                     case System.Windows.Forms.Keys.Right:
    03700                     case System.Windows.Forms.Keys.Down:
    03701                         SetValueInternal(currentValue + 1, true);
    03702                         return true;
    03703                 }
    03704             }
    03705
    03706             return false;
    03707         }
    03708
    03709
    03711         public override void Render(Device device, float elapsedTime)
    03712         {
    03713             ControlState state = ControlState.Normal;
    03714             if (IsVisible == false)
    03715             {
    03716                 state = ControlState.Hidden;
    03717             }
    03718             else if (IsEnabled == false)
    03719             {
    03720                 state = ControlState.Disabled;
    03721             }
    03722             else if (isPressed)
    03723             {
    03724                 state = ControlState.Pressed;
    03725             }
    03726             else if (isMouseOver)
    03727             {
    03728                 state = ControlState.MouseOver;
    03729             }
    03730             else if (hasFocus)
    03731             {
    03732                 state = ControlState.Focus;
    03733             }
    03734
    03735             float blendRate = (state == ControlState.Pressed) ? 0.0f : 0.8f;
    03736
    03737             Element e = elementList[Slider.TrackLayer] as Element;
    03738
    03739             // Blend current color
    03740             e.TextureColor.Blend(state, elapsedTime, blendRate);
    03741             parentDialog.DrawSprite(e, boundingBox);
    03742
    03743             e = elementList[Slider.ButtonLayer] as Element;
    03744             // Blend current color
    03745             e.TextureColor.Blend(state, elapsedTime, blendRate);
    03746             parentDialog.DrawSprite(e, buttonRect);
    03747         }
    03748     }
    03749     #endregion
    03750
    03751     #region Listbox Control
    03752
    03754     public enum ListBoxStyle
    03755     {
    03756         SingleSelection,
    03757         Multiselection,
    03758     }
    03759
    03761     public struct ListBoxItem
    03762     {
    03763         public string ItemText;
    03764         public object ItemData;
    03765         public System.Drawing.Rectangle ItemRect;
    03766         public bool IsItemSelected;
    03767     }
    03769     public class ListBox : Control
    03770     {
    03771         public const int MainLayer = 0;
    03772         public const int SelectionLayer = 1;
    03773
    03774         #region Event code
    03775         public event EventHandler ContentsChanged;
    03776         public event EventHandler DoubleClick;
    03777         public event EventHandler Selection;
    03779         protected void RaiseContentsChangedEvent(ListBox sender, bool wasTriggeredByUser)
    03780         {
    03781             // Discard events triggered programatically if these types of events haven't been
    03782             // enabled
    03783             if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
    03784                 return;
    03785
    03786             // Fire the event
    03787             if (ContentsChanged != null)
    03788                 ContentsChanged(sender, EventArgs.Empty);
    03789         }
    03791         protected void RaiseDoubleClickEvent(ListBox sender, bool wasTriggeredByUser)
    03792         {
    03793             // Discard events triggered programatically if these types of events haven't been
    03794             // enabled
    03795             if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
    03796                 return;
    03797
    03798             // Fire the event
    03799             if (DoubleClick != null)
    03800                 DoubleClick(sender, EventArgs.Empty);
    03801         }
    03803         protected void RaiseSelectionEvent(ListBox sender, bool wasTriggeredByUser)
    03804         {
    03805             // Discard events triggered programatically if these types of events haven't been
    03806             // enabled
    03807             if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
    03808                 return;
    03809
    03810             // Fire the event
    03811             if (Selection != null)
    03812                 Selection(sender, EventArgs.Empty);
    03813         }
    03814         #endregion
    03815
    03816         #region Instance data
    03817         private bool isScrollBarInit;
    03818         protected System.Drawing.Rectangle textRect; // Text rendering bound
    03819         protected System.Drawing.Rectangle selectionRect; // Selection box bound
    03820         protected ScrollBar scrollbarControl;
    03821         protected int scrollWidth;
    03822         protected int border;
    03823         protected int margin;
    03824         protected int textHeight; // Height of a single line of text
    03825         protected int selectedIndex;
    03826         protected int selectedStarted;
    03827         protected bool isDragging;
    03828         protected ListBoxStyle style;
    03829
    03830         protected ArrayList itemList;
    03831         #endregion
    03832
    03834         public ListBox(Dialog parent) : base(parent)
    03835         {
    03836             // Store control type and parent dialog
    03837             controlType = ControlType.ListBox;
    03838             parentDialog = parent;
    03839             // Create the scrollbar control too
    03840             scrollbarControl = new ScrollBar(parent);
    03841
    03842             // Set some default items
    03843             style = ListBoxStyle.SingleSelection;
    03844             scrollWidth = 16;
    03845             selectedIndex = -1;
    03846             selectedStarted = 0;
    03847             isDragging = false;
    03848             margin = 5;
    03849             border = 6;
    03850             textHeight = 0;
    03851             isScrollBarInit = false;
    03852
    03853             // Create the item list array
    03854             itemList = new ArrayList();
    03855         }
    03856
    03858         protected override void UpdateRectangles()
    03859         {
    03860             // Get bounding box
    03861             base.UpdateRectangles();
    03862
    03863             // Calculate the size of the selection rectangle
    03864             selectionRect = boundingBox;
    03865             selectionRect.Width -= scrollWidth;
    03866             selectionRect.Inflate(-border, -border);
    03867             textRect = selectionRect;
    03868             textRect.Inflate(-margin, 0);
    03869
    03870             // Update the scroll bars rects too
    03871             scrollbarControl.SetLocation(boundingBox.Right - scrollWidth, boundingBox.Top);
    03872             scrollbarControl.SetSize(scrollWidth, height);
    03873             FontNode fNode = DialogResourceManager.GetGlobalInstance().GetFontNode((int)(elementList[0] as Element).FontIndex);
    03874             if ((fNode != null) && (fNode.Height > 0))
    03875             {
    03876                 scrollbarControl.PageSize = (int)(textRect.Height / fNode.Height);
    03877
    03878                 // The selected item may have been scrolled off the page.
    03879                 // Ensure that it is in page again.
    03880                 scrollbarControl.ShowItem(selectedIndex);
    03881             }
    03882         }
    03884         public void SetScrollbarWidth(int width) { scrollWidth = width; UpdateRectangles(); }
    03886         public override bool CanHaveFocus { get { return (IsVisible && IsEnabled); } }
    03888         public ListBoxStyle Style { get { return style; } set { style = value; } }
    03890         public int NumberItems { get { return itemList.Count; } }
    03892         public ListBoxItem this[int index]
    03893         {
    03894             get { return (ListBoxItem)itemList[index]; }
    03895         }
    03896
    03898         public override void OnInitialize()
    03899         {
    03900             parentDialog.InitializeControl(scrollbarControl);
    03901         }
    03902
    03903
    03905         public override bool HandleKeyboard(NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
    03906         {
    03907             if (!IsEnabled || !IsVisible)
    03908                 return false;
    03909
    03910             // Let the scroll bar have a chance to handle it first
    03911             if (scrollbarControl.HandleKeyboard(msg, wParam, lParam))
    03912                 return true;
    03913
    03914             switch (msg)
    03915             {
    03916                 case NativeMethods.WindowMessage.KeyDown:
    03917                 {
    03918                     switch((System.Windows.Forms.Keys)wParam.ToInt32())
    03919                     {
    03920                         case System.Windows.Forms.Keys.Up:
    03921                         case System.Windows.Forms.Keys.Down:
    03922                         case System.Windows.Forms.Keys.Next:
    03923                         case System.Windows.Forms.Keys.Prior:
    03924                         case System.Windows.Forms.Keys.Home:
    03925                         case System.Windows.Forms.Keys.End:
    03926                         {
    03927                             // If no items exists, do nothing
    03928                             if (itemList.Count == 0)
    03929                                 return true;
    03930
    03931                             int oldSelected = selectedIndex;
    03932
    03933                             // Adjust selectedIndex
    03934                             switch((System.Windows.Forms.Keys)wParam.ToInt32())
    03935                             {
    03936                                 case System.Windows.Forms.Keys.Up: --selectedIndex; break;
    03937                                 case System.Windows.Forms.Keys.Down: ++selectedIndex; break;
    03938                                 case System.Windows.Forms.Keys.Next: selectedIndex += scrollbarControl.PageSize - 1; break;
    03939                                 case System.Windows.Forms.Keys.Prior: selectedIndex -= scrollbarControl.PageSize - 1; break;
    03940                                 case System.Windows.Forms.Keys.Home: selectedIndex = 0; break;
    03941                                 case System.Windows.Forms.Keys.End: selectedIndex = itemList.Count - 1; break;
    03942                             }
    03943
    03944                             // Clamp the item
    03945                             if (selectedIndex < 0)
    03946                                 selectedIndex = 0;
    03947                             if (selectedIndex >= itemList.Count)
    03948                                 selectedIndex = itemList.Count - 1;
    03949
    03950                             // Did the selection change?
    03951                             if (oldSelected != selectedIndex)
    03952                             {
    03953                                 if (style == ListBoxStyle.Multiselection)
    03954                                 {
    03955                                     // Clear all selection
    03956                                     for(int i = 0; i < itemList.Count; i++)
    03957                                     {
    03958                                         ListBoxItem lbi = (ListBoxItem)itemList[i];
    03959                                         lbi.IsItemSelected = false;
    03960                                         itemList[i] = lbi;
    03961                                     }
    03962
    03963                                     // Is shift being held down?
    03964                                     bool shiftDown = ((NativeMethods.GetAsyncKeyState
    03965                                         ((int)System.Windows.Forms.Keys.ShiftKey) & 0x8000) != 0);
    03966
    03967                                     if (shiftDown)
    03968                                     {
    03969                                         // Select all items from the start selection to current selected index
    03970                                         int end = Math.Max(selectedStarted, selectedIndex);
    03971                                         for(int i = Math.Min(selectedStarted, selectedIndex); i <= end; ++i)
    03972                                         {
    03973                                             ListBoxItem lbi = (ListBoxItem)itemList[i];
    03974                                             lbi.IsItemSelected = true;
    03975                                             itemList[i] = lbi;
    03976                                         }
    03977                                     }
    03978                                     else
    03979                                     {
    03980                                         ListBoxItem lbi = (ListBoxItem)itemList[selectedIndex];
    03981                                         lbi.IsItemSelected = true;
    03982                                         itemList[selectedIndex] = lbi;
    03983
    03984                                         // Update selection start
    03985                                         selectedStarted = selectedIndex;
    03986                                     }
    03987
    03988                                 }
    03989                                 else // Update selection start
    03990                                     selectedStarted = selectedIndex;
    03991
    03992                                 // adjust scrollbar
    03993                                 scrollbarControl.ShowItem(selectedIndex);
    03994                                 RaiseSelectionEvent(this, true);
    03995                             }
    03996                         }
    03997                         return true;
    03998                     }
    03999                     break;
    04000                 }
    04001             }
    04002
    04003             return false;
    04004         }
    04005
    04007         public override bool HandleMouse(NativeMethods.WindowMessage msg, System.Drawing.Point pt, IntPtr wParam, IntPtr lParam)
    04008         {
    04009             const int ShiftModifier = 0x0004;
    04010             const int ControlModifier = 0x0008;
    04011
    04012             if (!IsEnabled || !IsVisible)
    04013                 return false; // Nothing to do
    04014
    04015             // First acquire focus
    04016             if (msg == NativeMethods.WindowMessage.LeftButtonDown)
    04017                 if (!hasFocus)
    04018                     Dialog.RequestFocus(this);
    04019
    04020
    04021             // Let the scroll bar handle it first
    04022             if (scrollbarControl.HandleMouse(msg, pt, wParam, lParam))
    04023                 return true;
    04024
    04025             // Ok, scrollbar didn't handle it, move on
    04026             switch(msg)
    04027             {
    04028                 case NativeMethods.WindowMessage.LeftButtonDoubleClick:
    04029                 case NativeMethods.WindowMessage.LeftButtonDown:
    04030                 {
    04031                     // Check for clicks in the text area
    04032                     if (itemList.Count > 0 && selectionRect.Contains(pt))
    04033                     {
    04034                         // Compute the index of the clicked item
    04035                         int clicked = 0;
    04036                         if (textHeight > 0)
    04037                             clicked = scrollbarControl.TrackPosition + (pt.Y - textRect.Top) / textHeight;
    04038                         else
    04039                             clicked = -1;
    04040
    04041                         // Only proceed if the click falls ontop of an item
    04042                         if (clicked >= scrollbarControl.TrackPosition &&
    04043                             clicked < itemList.Count &&
    04044                             clicked < scrollbarControl.TrackPosition + scrollbarControl.PageSize )
    04045                         {
    04046                             Parent.SampleFramework.Window.Capture = true;
    04047                             isDragging = true;
    04048
    04049                             // If this is a double click, fire off an event and exit
    04050                             // since the first click would have taken care of the selection
    04051                             // updating.
    04052                             if (msg == NativeMethods.WindowMessage.LeftButtonDoubleClick)
    04053                             {
    04054                                 RaiseDoubleClickEvent(this, true);
    04055                                 return true;
    04056                             }
    04057
    04058                             selectedIndex = clicked;
    04059                             if ( (wParam.ToInt32() & ShiftModifier) == 0)
    04060                                 selectedStarted = selectedIndex; // Shift isn't down
    04061
    04062                             // If this is a multi-selection listbox, update per-item
    04063                             // selection data.
    04064                             if (style == ListBoxStyle.Multiselection)
    04065                             {
    04066                                 // Determine behavior based on the state of Shift and Ctrl
    04067                                 ListBoxItem selectedItem = (ListBoxItem)itemList[selectedIndex];
    04068                                 if ((wParam.ToInt32() & (ShiftModifier | ControlModifier)) == ControlModifier)
    04069                                 {
    04070                                     // Control click, reverse the selection
    04071                                     selectedItem.IsItemSelected = !selectedItem.IsItemSelected;
    04072                                     itemList[selectedIndex] = selectedItem;
    04073                                 }
    04074                                 else if ((wParam.ToInt32() & (ShiftModifier | ControlModifier)) == ShiftModifier)
    04075                                 {
    04076                                     // Shift click. Set the selection for all items
    04077                                     // from last selected item to the current item.
    04078                                     // Clear everything else.
    04079                                     int begin = Math.Min(selectedStarted, selectedIndex);
    04080                                     int end = Math.Max(selectedStarted, selectedIndex);
    04081
    04082                                     // Unselect everthing before the beginning
    04083                                     for(int i = 0; i < begin; ++i)
    04084                                     {
    04085                                         ListBoxItem lb = (ListBoxItem)itemList[i];
    04086                                         lb.IsItemSelected = false;
    04087                                         itemList[i] = lb;
    04088                                     }
    04089                                     // unselect everything after the end
    04090                                     for(int i = end + 1; i < itemList.Count; ++i)
    04091                                     {
    04092                                         ListBoxItem lb = (ListBoxItem)itemList[i];
    04093                                         lb.IsItemSelected = false;
    04094                                         itemList[i] = lb;
    04095                                     }
    04096
    04097                                     // Select everything between
    04098                                     for(int i = begin; i <= end; ++i)
    04099                                     {
    04100                                         ListBoxItem lb = (ListBoxItem)itemList[i];
    04101                                         lb.IsItemSelected = true;
    04102                                         itemList[i] = lb;
    04103                                     }
    04104                                 }
    04105                                 else if ((wParam.ToInt32() & (ShiftModifier | ControlModifier)) == (ShiftModifier | ControlModifier))
    04106                                 {
    04107                                     // Control-Shift-click.
    04108
    04109                                     // The behavior is:
    04110                                     //   Set all items from selectedStarted to selectedIndex to
    04111                                     //     the same state as selectedStarted, not including selectedIndex.
    04112                                     //   Set selectedIndex to selected.
    04113                                     int begin = Math.Min(selectedStarted, selectedIndex);
    04114                                     int end = Math.Max(selectedStarted, selectedIndex);
    04115
    04116                                     // The two ends do not need to be set here.
    04117                                     bool isLastSelected = ((ListBoxItem)itemList[selectedStarted]).IsItemSelected;
    04118
    04119                                     for (int i = begin + 1; i < end; ++i)
    04120                                     {
    04121                                         ListBoxItem lb = (ListBoxItem)itemList[i];
    04122                                         lb.IsItemSelected = isLastSelected;
    04123                                         itemList[i] = lb;
    04124                                     }
    04125
    04126                                     selectedItem.IsItemSelected = true;
    04127                                     itemList[selectedIndex] = selectedItem;
    04128
    04129                                     // Restore selectedIndex to the previous value
    04130                                     // This matches the Windows behavior
    04131
    04132                                     selectedIndex = selectedStarted;
    04133                                 }
    04134                                 else
    04135                                 {
    04136                                     // Simple click.  Clear all items and select the clicked
    04137                                     // item.
    04138                                     for(int i = 0; i < itemList.Count; ++i)
    04139                                     {
    04140                                         ListBoxItem lb = (ListBoxItem)itemList[i];
    04141                                         lb.IsItemSelected = false;
    04142                                         itemList[i] = lb;
    04143                                     }
    04144                                     selectedItem.IsItemSelected = true;
    04145                                     itemList[selectedIndex] = selectedItem;
    04146                                 }
    04147                             } // End of multi-selection case
    04148                             RaiseSelectionEvent(this, true);
    04149                         }
    04150                         return true;
    04151                     }
    04152                     break;
    04153                 }
    04154                 case NativeMethods.WindowMessage.LeftButtonUp:
    04155                 {
    04156                     Parent.SampleFramework.Window.Capture = false;
    04157                     isDragging = false;
    04158
    04159                     if (selectedIndex != -1)
    04160                     {
    04161                         // Set all items between selectedStarted and selectedIndex to
    04162                         // the same state as selectedStarted
    04163                         int end = Math.Max(selectedStarted, selectedIndex);
    04164                         for (int i = Math.Min(selectedStarted, selectedIndex) + 1; i < end; ++i)
    04165                         {
    04166                             ListBoxItem lb = (ListBoxItem)itemList[i];
    04167                             lb.IsItemSelected = ((ListBoxItem)itemList[selectedStarted]).IsItemSelected;
    04168                             itemList[i] = lb;
    04169                         }
    04170                         ListBoxItem lbs = (ListBoxItem)itemList[selectedIndex];
    04171                         lbs.IsItemSelected = ((ListBoxItem)itemList[selectedStarted]).IsItemSelected;
    04172                         itemList[selectedIndex] = lbs;
    04173
    04174                         // If selectedStarted and selectedIndex are not the same,
    04175                         // the user has dragged the mouse to make a selection.
    04176                         // Notify the application of this.
    04177                         if (selectedIndex != selectedStarted)
    04178                             RaiseSelectionEvent(this, true);
    04179                     }
    04180                     break;
    04181                 }
    04182                 case NativeMethods.WindowMessage.MouseWheel:
    04183                 {
    04184                     int lines = System.Windows.Forms.SystemInformation.MouseWheelScrollLines;
    04185                     int scrollAmount = (int)(NativeMethods.HiWord((uint)wParam.ToInt32()) / Dialog.WheelDelta * lines);
    04186                     scrollbarControl.Scroll(-scrollAmount);
    04187                     break;
    04188                 }
    04189
    04190                 case NativeMethods.WindowMessage.MouseMove:
    04191                 {
    04192                     if (isDragging)
    04193                     {
    04194                         // compute the index of the item below the cursor
    04195                         int itemIndex = -1;
    04196                         if (textHeight > 0)
    04197                             itemIndex = scrollbarControl.TrackPosition + (pt.Y - textRect.Top) / textHeight;
    04198
    04199                         // Only proceed if the cursor is on top of an item
    04200                         if (itemIndex >= scrollbarControl.TrackPosition &&
    04201                             itemIndex < itemList.Count &&
    04202                             itemIndex < scrollbarControl.TrackPosition + scrollbarControl.PageSize)
    04203                         {
    04204                             selectedIndex = itemIndex;
    04205                             RaiseSelectionEvent(this, true);
    04206                         }
    04207                         else if (itemIndex < scrollbarControl.TrackPosition)
    04208                         {
    04209                             // User drags the mouse above window top
    04210                             scrollbarControl.Scroll(-1);
    04211                             selectedIndex = scrollbarControl.TrackPosition;
    04212                             RaiseSelectionEvent(this, true);
    04213                         }
    04214                         else if (itemIndex >= scrollbarControl.TrackPosition + scrollbarControl.PageSize)
    04215                         {
    04216                             // User drags the mouse below the window bottom
    04217                             scrollbarControl.Scroll(1);
    04218                             selectedIndex = Math.Min(itemList.Count, scrollbarControl.TrackPosition + scrollbarControl.PageSize - 1);
    04219                             RaiseSelectionEvent(this, true);
    04220                         }
    04221                     }
    04222                     break;
    04223                 }
    04224             }
    04225
    04226             // Didn't handle it
    04227             return false;
    04228         }
    04229
    04231         public override void Render(Device device, float elapsedTime)
    04232         {
    04233             if (!IsVisible)
    04234                 return; // Nothing to render
    04235
    04236             Element e = elementList[ListBox.MainLayer] as Element;
    04237
    04238             // Blend current color
    04239             e.TextureColor.Blend(ControlState.Normal, elapsedTime);
    04240             e.FontColor.Blend(ControlState.Normal, elapsedTime);
    04241
    04242             Element selectedElement = elementList[ListBox.SelectionLayer] as Element;
    04243
    04244             // Blend current color
    04245             selectedElement.TextureColor.Blend(ControlState.Normal, elapsedTime);
    04246             selectedElement.FontColor.Blend(ControlState.Normal, elapsedTime);
    04247
    04248             parentDialog.DrawSprite(e, boundingBox);
    04249
    04250             // Render the text
    04251             if (itemList.Count > 0)
    04252             {
    04253                 // Find out the height of a single line of text
    04254                 System.Drawing.Rectangle rc = textRect;
    04255                 System.Drawing.Rectangle sel = selectionRect;
    04256                 rc.Height = (int)(DialogResourceManager.GetGlobalInstance().GetFontNode((int)e.FontIndex).Height);
    04257                 textHeight = rc.Height;
    04258
    04259                 // If we have not initialized the scroll bar page size,
    04260                 // do that now.
    04261                 if (!isScrollBarInit)
    04262                 {
    04263                     if (textHeight > 0)
    04264                         scrollbarControl.PageSize = (int)(textRect.Height / textHeight);
    04265                     else
    04266                         scrollbarControl.PageSize = textRect.Height;
    04267
    04268                     isScrollBarInit = true;
    04269                 }
    04270                 rc.Width = textRect.Width;
    04271                 for (int i = scrollbarControl.TrackPosition; i < itemList.Count; ++i)
    04272                 {
    04273                     if (rc.Bottom > textRect.Bottom)
    04274                         break;
    04275
    04276                     ListBoxItem lb = (ListBoxItem)itemList[i];
    04277
    04278                     // Determine if we need to render this item with the
    04279                     // selected element.
    04280                     bool isSelectedStyle = false;
    04281
    04282                     if ( (selectedIndex == i) && (style == ListBoxStyle.SingleSelection) )
    04283                         isSelectedStyle = true;
    04284                     else if (style == ListBoxStyle.Multiselection)
    04285                     {
    04286                         if (isDragging && ( ( i >= selectedIndex && i < selectedStarted) ||
    04287                             (i <= selectedIndex && i > selectedStarted) ) )
    04288                         {
    04289                             ListBoxItem selStart = (ListBoxItem)itemList[selectedStarted];
    04290                             isSelectedStyle = selStart.IsItemSelected;
    04291                         }
    04292                         else
    04293                             isSelectedStyle = lb.IsItemSelected;
    04294                     }
    04295
    04296                     // Now render the text
    04297                     if (isSelectedStyle)
    04298                     {
    04299                         sel.Location = new System.Drawing.Point(sel.Left, rc.Top);
    04300                         sel.Height = rc.Height;
    04301                         parentDialog.DrawSprite(selectedElement, sel);
    04302                         parentDialog.DrawText(lb.ItemText, selectedElement, rc);
    04303                     }
    04304                     else
    04305                         parentDialog.DrawText(lb.ItemText, e, rc);
    04306
    04307                     rc.Offset(0, textHeight);
    04308                 }
    04309             }
    04310
    04311             // Render the scrollbar finally
    04312             scrollbarControl.Render(device, elapsedTime);
    04313         }
    04314
    04315
    04316         #region Item Controlling methods
    04318         public void AddItem(string text, object data)
    04319         {
    04320             if ((text == null) || (text.Length == 0))
    04321                 throw new ArgumentNullException("text", "You must pass in a valid item name when adding a new item.");
    04322
    04323             // Create a new item and add it
    04324             ListBoxItem newitem = new ListBoxItem();
    04325             newitem.ItemText = text;
    04326             newitem.ItemData = data;
    04327             newitem.IsItemSelected = false;
    04328             itemList.Add(newitem);
    04329
    04330             // Update the scrollbar with the new range
    04331             scrollbarControl.SetTrackRange(0, itemList.Count);
    04332         }
    04334         public void InsertItem(int index, string text, object data)
    04335         {
    04336             if ((text == null) || (text.Length == 0))
    04337                 throw new ArgumentNullException("text", "You must pass in a valid item name when adding a new item.");
    04338
    04339             // Create a new item and insert it
    04340             ListBoxItem newitem = new ListBoxItem();
    04341             newitem.ItemText = text;
    04342             newitem.ItemData = data;
    04343             newitem.IsItemSelected = false;
    04344             itemList.Insert(index, newitem);
    04345
    04346             // Update the scrollbar with the new range
    04347             scrollbarControl.SetTrackRange(0, itemList.Count);
    04348         }
    04349
    04351         public void RemoveAt(int index)
    04352         {
    04353             // Remove the item
    04354             itemList.RemoveAt(index);
    04355
    04356             // Update the scrollbar with the new range
    04357             scrollbarControl.SetTrackRange(0, itemList.Count);
    04358
    04359             if (selectedIndex >= itemList.Count)
    04360                 selectedIndex = itemList.Count - 1;
    04361
    04362             RaiseSelectionEvent(this, true);
    04363         }
    04364
    04366         public void Clear()
    04367         {
    04368             // clear the list
    04369             itemList.Clear();
    04370
    04371             // Update scroll bar and index
    04372             scrollbarControl.SetTrackRange(0, 1);
    04373             selectedIndex = -1;
    04374         }
    04375
    04384         public int GetSelectedIndex(int previousSelected)
    04385         {
    04386             if (previousSelected < -1)
    04387                 return -1;
    04388
    04389             if (style == ListBoxStyle.Multiselection)
    04390             {
    04391                 // Multiple selections enabled.  Search for the next item with the selected flag
    04392                 for (int i = previousSelected + 1; i < itemList.Count; ++i)
    04393                 {
    04394                     ListBoxItem lbi = (ListBoxItem)itemList[i];
    04395                     if (lbi.IsItemSelected)
    04396                         return i;
    04397                 }
    04398
    04399                 return -1;
    04400             }
    04401             else
    04402             {
    04403                 // Single selection
    04404                 return selectedIndex;
    04405             }
    04406         }
    04408         public ListBoxItem GetSelectedItem(int previousSelected)
    04409         {
    04410             return (ListBoxItem)itemList[GetSelectedIndex(previousSelected)];
    04411         }
    04413         public ListBoxItem GetSelectedItem() { return GetSelectedItem(-1); }
    04414
    04416         public void SetBorder(int borderSize, int marginSize)
    04417         {
    04418             border = borderSize;
    04419             margin = marginSize;
    04420             UpdateRectangles();
    04421         }
    04422
    04424         public void SelectItem(int newIndex)
    04425         {
    04426             if (itemList.Count == 0)
    04427                 return; // If no items exist there's nothing to do
    04428
    04429             int oldSelected = selectedIndex;
    04430
    04431             // Select the new item
    04432             selectedIndex = newIndex;
    04433
    04434             // Clamp the item
    04435             if (selectedIndex < 0)
    04436                 selectedIndex = 0;
    04437             if (selectedIndex > itemList.Count)
    04438                 selectedIndex = itemList.Count - 1;
    04439
    04440             // Did the selection change?
    04441             if (oldSelected != selectedIndex)
    04442             {
    04443                 if (style == ListBoxStyle.Multiselection)
    04444                 {
    04445                     ListBoxItem lbi = (ListBoxItem)itemList[selectedIndex];
    04446                     lbi.IsItemSelected = true;
    04447                     itemList[selectedIndex] = lbi;
    04448                 }
    04449
    04450                 // Update selection start
    04451                 selectedStarted = selectedIndex;
    04452
    04453                 // adjust scrollbar
    04454                 scrollbarControl.ShowItem(selectedIndex);
    04455             }
    04456             RaiseSelectionEvent(this, true);
    04457         }
    04458         #endregion
    04459     }
    04460     #endregion
    04461
    04463     public class EditBox : Control
    04464     {
    04465         #region Element layers
    04466         public const int TextLayer = 0;
    04467         public const int TopLeftBorder = 1;
    04468         public const int TopBorder = 2;
    04469         public const int TopRightBorder = 3;
    04470         public const int LeftBorder = 4;
    04471         public const int RightBorder = 5;
    04472         public const int LowerLeftBorder = 6;
    04473         public const int LowerBorder = 7;
    04474         public const int LowerRightBorder = 8;
    04475         #endregion
    04476
    04477         #region Event code
    04478         public event EventHandler Changed;
    04479         public event EventHandler Enter;
    04481         protected void RaiseChangedEvent(EditBox sender, bool wasTriggeredByUser)
    04482         {
    04483             // Discard events triggered programatically if these types of events haven't been
    04484             // enabled
    04485             if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
    04486                 return;
    04487
    04488             if (Changed != null)
    04489                 Changed(sender, EventArgs.Empty);
    04490         }
    04492         protected void RaiseEnterEvent(EditBox sender, bool wasTriggeredByUser)
    04493         {
    04494             // Discard events triggered programatically if these types of events haven't been
    04495             // enabled
    04496             if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
    04497                 return;
    04498
    04499             if (Enter != null)
    04500                 Enter(sender, EventArgs.Empty);
    04501         }
    04502         #endregion
    04503
    04504         #region Class Data
    04505         protected System.Windows.Forms.RichTextBox textData; // Text data
    04506         protected int border; // Border of the window
    04507         protected int spacing; // Spacing between the text and the edge of border
    04508         protected System.Drawing.Rectangle textRect; // Bounding rectangle for the text
    04509         protected System.Drawing.Rectangle[] elementRects = new System.Drawing.Rectangle[9];
    04510         protected double blinkTime; // Caret blink time in milliseconds
    04511         protected double lastBlink; // Last timestamp of caret blink
    04512         protected bool isCaretOn; // Flag to indicate whether caret is currently visible
    04513         protected int caretPosition; // Caret position, in characters
    04514         protected bool isInsertMode; // If true, control is in insert mode. Else, overwrite mode.
    04515         protected int firstVisible;  // First visible character in the edit control
    04516         protected ColorValue textColor; // Text color
    04517         protected ColorValue selectedTextColor; // Selected Text color
    04518         protected ColorValue selectedBackColor; // Selected background color
    04519         protected ColorValue caretColor; // Caret color
    04520
    04521         // Mouse-specific
    04522         protected bool isMouseDragging; // True to indicate the drag is in progress
    04523
    04524         protected static bool isHidingCaret; // If true, we don't render the caret.
    04525
    04526         #endregion
    04527
    04528         #region Simple overrides/properties/methods
    04530         public override bool CanHaveFocus { get { return (IsVisible && IsEnabled); } }
    04532         public void SetSpacing(int space) { spacing = space; UpdateRectangles(); }
    04534         public void SetBorderWidth(int b) { border = b; UpdateRectangles(); }
    04536         public void SetTextColor(ColorValue color) { textColor = color; }
    04538         public void SetSelectedTextColor(ColorValue color) { selectedTextColor = color; }
    04540         public void SetSelectedBackColor(ColorValue color) { selectedBackColor = color; }
    04542         public void SetCaretColor(ColorValue color) { caretColor = color; }
    04543
    04545         public string Text { get { return textData.Text; } set { SetText(value, false); } }
    04547         public string GetTextCopy() { return string.Copy(textData.Text); }
    04548         #endregion
    04549
    04551         public EditBox(Dialog parent) : base(parent)
    04552         {
    04553             controlType = ControlType.EditBox;
    04554             parentDialog = parent;
    04555
    04556             border = 5; // Default border
    04557             spacing = 4; // default spacing
    04558             isCaretOn = true;
    04559
    04560             textData = new System.Windows.Forms.RichTextBox();
    04561             // Create the control
    04562             textData.Visible = true;
    04563             textData.Font = new System.Drawing.Font("Arial", 8.0f);
    04564             textData.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
    04565             textData.Multiline = false;
    04566             textData.Text = string.Empty;
    04567             textData.MaxLength = ushort.MaxValue; // 65k characters should be plenty
    04568             textData.WordWrap = false;
    04569             // Now create the control
    04570             textData.CreateControl();
    04571
    04572             isHidingCaret = false;
    04573             firstVisible = 0;
    04574             blinkTime = NativeMethods.GetCaretBlinkTime() * 0.001f;
    04575             lastBlink = FrameworkTimer.GetAbsoluteTime();
    04576             textColor = new ColorValue(0.06f, 0.06f, 0.06f, 1.0f);
    04577             selectedTextColor = new ColorValue(1.0f, 1.0f, 1.0f, 1.0f);
    04578             selectedBackColor = new ColorValue(0.15f, 0.196f, 0.36f, 1.0f);
    04579             caretColor = new ColorValue(0, 0, 0, 1.0f);
    04580             caretPosition = textData.SelectionStart = 0;
    04581             isInsertMode = true;
    04582             isMouseDragging = false;
    04583         }
    04584
    04586         protected void PlaceCaret(int pos)
    04587         {
    04588             // Store caret position
    04589             caretPosition = pos;
    04590
    04591             // First find the first visible char
    04592             for (int i = 0; i < textData.Text.Length; i++)
    04593             {
    04594                 System.Drawing.Point p = textData.GetPositionFromCharIndex(i);
    04595                 if (p.X >= 0)
    04596                 {
    04597                     firstVisible = i; // This is the first visible character
    04598                     break;
    04599                 }
    04600             }
    04601
    04602             // if the new position is smaller than the first visible char
    04603             // we'll need to scroll
    04604             if (firstVisible > caretPosition)
    04605                 firstVisible = caretPosition;
    04606         }
    04607
    04609         public void Clear()
    04610         {
    04611             textData.Text = string.Empty;
    04612             PlaceCaret(0);
    04613             textData.SelectionStart = 0;
    04614         }
    04616         public void SetText(string text, bool selected)
    04617         {
    04618             if (text == null)
    04619                 text = string.Empty;
    04620
    04621             textData.Text = text;
    04622             textData.SelectionStart = text.Length;
    04623             // Move the care to the end of the text
    04624             PlaceCaret(text.Length);
    04625             textData.SelectionStart = (selected) ? 0 : caretPosition;
    04626             FocusText();
    04627         }
    04629         protected void DeleteSelectionText()
    04630         {
    04631             int first = Math.Min(caretPosition, textData.SelectionStart);
    04632             int last = Math.Max(caretPosition, textData.SelectionStart);
    04633             // Update caret and selection
    04634             PlaceCaret(first);
    04635             // Remove the characters
    04636             textData.Text = textData.Text.Remove(first, (last-first));
    04637             textData.SelectionStart = caretPosition;
    04638             FocusText();
    04639         }
    04641         protected override void UpdateRectangles()
    04642         {
    04643             // Get the bounding box first
    04644             base.UpdateRectangles ();
    04645
    04646             // Update text rect
    04647             textRect = boundingBox;
    04648             // First inflate by border to compute render rects
    04649             textRect.Inflate(-border, -border);
    04650
    04651             // Update the render rectangles
    04652             elementRects[0] = textRect;
    04653             elementRects[1] = new System.Drawing.Rectangle(boundingBox.Left, boundingBox.Top, (textRect.Left - boundingBox.Left), (textRect.Top - boundingBox.Top));
    04654             elementRects[2] = new System.Drawing.Rectangle(textRect.Left, boundingBox.Top, textRect.Width, (textRect.Top - boundingBox.Top));
    04655             elementRects[3] = new System.Drawing.Rectangle(textRect.Right, boundingBox.Top, (boundingBox.Right - textRect.Right), (textRect.Top - boundingBox.Top));
    04656             elementRects[4] = new System.Drawing.Rectangle(boundingBox.Left, textRect.Top, (textRect.Left - boundingBox.Left), textRect.Height);
    04657             elementRects[5] = new System.Drawing.Rectangle(textRect.Right, textRect.Top, (boundingBox.Right - textRect.Right), textRect.Height);
    04658             elementRects[6] = new System.Drawing.Rectangle(boundingBox.Left, textRect.Bottom, (textRect.Left - boundingBox.Left), (boundingBox.Bottom - textRect.Bottom));
    04659             elementRects[7] = new System.Drawing.Rectangle(textRect.Left, textRect.Bottom, textRect.Width, (boundingBox.Bottom - textRect.Bottom));
    04660             elementRects[8] = new System.Drawing.Rectangle(textRect.Right, textRect.Bottom, (boundingBox.Right - textRect.Right), (boundingBox.Bottom - textRect.Bottom));
    04661
    04662             // Inflate further by spacing
    04663             textRect.Inflate(-spacing, -spacing);
    04664
    04665             // Make the underlying rich text box the same size
    04666             textData.Size = textRect.Size;
    04667         }
    04668
    04670         protected void CopyToClipboard()
    04671         {
    04672             // Copy the selection text to the clipboard
    04673             if (caretPosition != textData.SelectionStart)
    04674             {
    04675                 int first = Math.Min(caretPosition, textData.SelectionStart);
    04676                 int last = Math.Max(caretPosition, textData.SelectionStart);
    04677                 // Set the text to the clipboard
    04678                 System.Windows.Forms.Clipboard.SetDataObject(textData.Text.Substring(first, (last-first)));
    04679             }
    04680
    04681         }
    04683         protected void PasteFromClipboard()
    04684         {
    04685             // Get the clipboard data
    04686             System.Windows.Forms.IDataObject clipData = System.Windows.Forms.Clipboard.GetDataObject();
    04687             // Does the clipboard have string data?
    04688             if (clipData.GetDataPresent(System.Windows.Forms.DataFormats.StringFormat))
    04689             {
    04690                 // Yes, get that data
    04691                 string clipString = clipData.GetData(System.Windows.Forms.DataFormats.StringFormat) as string;
    04692                 // find any new lines, remove everything after that
    04693                 int index;
    04694                 if ((index = clipString.IndexOf("\n")) > 0)
    04695                 {
    04696                     clipString = clipString.Substring(0, index-1);
    04697                 }
    04698
    04699                 // Insert that into the text data
    04700                 textData.Text = textData.Text.Insert(caretPosition, clipString);
    04701                 caretPosition += clipString.Length;
    04702                 textData.SelectionStart = caretPosition;
    04703                 FocusText();
    04704             }
    04705         }
    04707         protected void ResetCaretBlink()
    04708         {
    04709             isCaretOn = true;
    04710             lastBlink = FrameworkTimer.GetAbsoluteTime();
    04711         }
    04712
    04714         public override void OnFocusIn()
    04715         {
    04716             base.OnFocusIn();
    04717             ResetCaretBlink();
    04718         }
    04719
    04721         private void FocusText()
    04722         {
    04723             // Because of a design issue with the rich text box control that is used as
    04724             // the backing store for this control, the 'scrolling' mechanism built into
    04725             // the control will only work if the control has focus.  Setting focus to the
    04726             // control here would work, but would cause a bad 'flicker' of the application.
    04727
    04728             // Therefore, the automatic horizontal scrolling is turned off by default.  To
    04729             // enable it turn this define on.
    04730 #if (SCROLL_CORRECTLY)
    04731             NativeMethods.SetFocus(textData.Handle);
    04732             NativeMethods.SetFocus(Parent.SampleFramework.Window);
    04733 #endif
    04734         }
    04735
    04737         public override bool HandleKeyboard(Microsoft.Samples.DirectX.UtilityToolkit.NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
    04738         {
    04739             if (!IsEnabled || !IsVisible)
    04740                 return false;
    04741
    04742             // Default to not handling the message
    04743             bool isHandled = false;
    04744             if (msg == NativeMethods.WindowMessage.KeyDown)
    04745             {
    04746                 switch((System.Windows.Forms.Keys)wParam.ToInt32())
    04747                 {
    04748                     case System.Windows.Forms.Keys.End:
    04749                     case System.Windows.Forms.Keys.Home:
    04750                         // Move the caret
    04751                         if (wParam.ToInt32() == (int)System.Windows.Forms.Keys.End)
    04752                             PlaceCaret(textData.Text.Length);
    04753                         else
    04754                             PlaceCaret(0);
    04755                         if (!NativeMethods.IsKeyDown(System.Windows.Forms.Keys.ShiftKey))
    04756                         {
    04757                             // Shift is not down. Update selection start along with caret
    04758                             textData.SelectionStart = caretPosition;
    04759                             FocusText();
    04760                         }
    04761
    04762                         ResetCaretBlink();
    04763                         isHandled = true;
    04764                         break;
    04765                     case System.Windows.Forms.Keys.Insert:
    04766                         if (NativeMethods.IsKeyDown(System.Windows.Forms.Keys.ControlKey))
    04767                         {
    04768                             // Control insert -> Copy to clipboard
    04769                             CopyToClipboard();
    04770                         }
    04771                         else if (NativeMethods.IsKeyDown(System.Windows.Forms.Keys.ShiftKey))
    04772                         {
    04773                             // Shift insert -> Paste from clipboard
    04774                             PasteFromClipboard();
    04775                         }
    04776                         else
    04777                         {
    04778                             // Toggle insert mode
    04779                             isInsertMode = !isInsertMode;
    04780                         }
    04781                         break;
    04782                     case System.Windows.Forms.Keys.Delete:
    04783                         // Check to see if there is a text selection
    04784                         if (caretPosition != textData.SelectionStart)
    04785                         {
    04786                             DeleteSelectionText();
    04787                             RaiseChangedEvent(this, true);
    04788                         }
    04789                         else
    04790                         {
    04791                             if (caretPosition < textData.Text.Length)
    04792                             {
    04793                                 // Deleting one character
    04794                                 textData.Text = textData.Text.Remove(caretPosition, 1);
    04795                                 RaiseChangedEvent(this, true);
    04796                             }
    04797                         }
    04798                         ResetCaretBlink();
    04799                         isHandled = true;
    04800                         break;
    04801
    04802                     case System.Windows.Forms.Keys.Left:
    04803                         if (NativeMethods.IsKeyDown(System.Windows.Forms.Keys.ControlKey))
    04804                         {
    04805                             // Control is down. Move the caret to a new item
    04806                             // instead of a character.
    04807                         }
    04808                         else if (caretPosition > 0)
    04809                             PlaceCaret(caretPosition - 1); // Move one to the left
    04810
    04811                         if (!NativeMethods.IsKeyDown(System.Windows.Forms.Keys.ShiftKey))
    04812                         {
    04813                             // Shift is not down. Update selection
    04814                             // start along with the caret.
    04815                             textData.SelectionStart = caretPosition;
    04816                             FocusText();
    04817                         }
    04818                         ResetCaretBlink();
    04819                         isHandled = true;
    04820                         break;
    04821
    04822                     case System.Windows.Forms.Keys.Right:
    04823                         if (NativeMethods.IsKeyDown(System.Windows.Forms.Keys.ControlKey))
    04824                         {
    04825                             // Control is down. Move the caret to a new item
    04826                             // instead of a character.
    04827                         }
    04828                         else if (caretPosition < textData.Text.Length)
    04829                             PlaceCaret(caretPosition + 1); // Move one to the left
    04830                         if (!NativeMethods.IsKeyDown(System.Windows.Forms.Keys.ShiftKey))
    04831                         {
    04832                             // Shift is not down. Update selection
    04833                             // start along with the caret.
    04834                             textData.SelectionStart = caretPosition;
    04835                             FocusText();
    04836                         }
    04837                         ResetCaretBlink();
    04838                         isHandled = true;
    04839                         break;
    04840
    04841                     case System.Windows.Forms.Keys.Up:
    04842                     case System.Windows.Forms.Keys.Down:
    04843                         // Trap up and down arrows so that the dialog
    04844                         // does not switch focus to another control.
    04845                         isHandled = true;
    04846                         break;
    04847
    04848                     default:
    04849                         // Let the application handle escape
    04850                         isHandled = ((System.Windows.Forms.Keys)wParam.ToInt32()) == System.Windows.Forms.Keys.Escape;
    04851                         break;
    04852                 }
    04853             }
    04854
    04855             return isHandled;
    04856         }
    04857
    04859         public override bool HandleMouse(NativeMethods.WindowMessage msg, System.Drawing.Point pt, IntPtr wParam, IntPtr lParam)
    04860         {
    04861             if (!IsEnabled || !IsVisible)
    04862                 return false;
    04863
    04864             // We need a new point
    04865             System.Drawing.Point p = pt;
    04866             p.X -= textRect.Left;
    04867             p.Y -= textRect.Top;
    04868
    04869             switch(msg)
    04870             {
    04871                 case NativeMethods.WindowMessage.LeftButtonDown:
    04872                 case NativeMethods.WindowMessage.LeftButtonDoubleClick:
    04873                     // Get focus first
    04874                     if (!hasFocus)
    04875                         Dialog.RequestFocus(this);
    04876
    04877                     if (!ContainsPoint(pt))
    04878                         return false;
    04879
    04880                     isMouseDragging = true;
    04881                     Parent.SampleFramework.Window.Capture = true;
    04882                     // Determine the character corresponding to the coordinates
    04883                     int index = textData.GetCharIndexFromPosition(p);
    04884
    04885                     System.Drawing.Point startPosition = textData.GetPositionFromCharIndex(index);
    04886
    04887                     if (p.X > startPosition.X && index < textData.Text.Length)
    04888                         PlaceCaret(index + 1);
    04889                     else
    04890                         PlaceCaret(index);
    04891
    04892                     textData.SelectionStart = caretPosition;
    04893                     FocusText();
    04894                     ResetCaretBlink();
    04895                     return true;
    04896
    04897                 case NativeMethods.WindowMessage.LeftButtonUp:
    04898                     Parent.SampleFramework.Window.Capture = false;
    04899                     isMouseDragging = false;
    04900                     break;
    04901                 case NativeMethods.WindowMessage.MouseMove:
    04902                     if (isMouseDragging)
    04903                     {
    04904                         // Determine the character corresponding to the coordinates
    04905                         int dragIndex = textData.GetCharIndexFromPosition(p);
    04906
    04907                         if (dragIndex < textData.Text.Length)
    04908                             PlaceCaret(dragIndex + 1);
    04909                         else
    04910                             PlaceCaret(dragIndex);
    04911                     }
    04912                     break;
    04913             }
    04914             return false;
    04915         }
    04916
    04918         public override bool MsgProc(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
    04919         {
    04920             if (!IsEnabled || !IsVisible)
    04921                 return false;
    04922
    04923             if (msg == NativeMethods.WindowMessage.Character)
    04924             {
    04925                 int charKey = wParam.ToInt32();
    04926                 switch(charKey)
    04927                 {
    04928                     case (int)System.Windows.Forms.Keys.Back:
    04929                     {
    04930                         // If there's a selection, treat this
    04931                         // like a delete key.
    04932                         if (caretPosition != textData.SelectionStart)
    04933                         {
    04934                             DeleteSelectionText();
    04935                             RaiseChangedEvent(this, true);
    04936                         }
    04937                         else if (caretPosition > 0)
    04938                         {
    04939                             // Move the caret and delete the char
    04940                             textData.Text = textData.Text.Remove(caretPosition - 1, 1);
    04941                             PlaceCaret(caretPosition - 1);
    04942                             textData.SelectionStart = caretPosition;
    04943                             FocusText();
    04944                             RaiseChangedEvent(this, true);
    04945                         }
    04946
    04947                         ResetCaretBlink();
    04948                         break;
    04949                     }
    04950                     case 24: // Ctrl-X Cut
    04951                     case (int)System.Windows.Forms.Keys.Cancel: // Ctrl-C Copy
    04952                     {
    04953                         CopyToClipboard();
    04954
    04955                         // If the key is Ctrl-X, delete the selection too.
    04956                         if (charKey == 24)
    04957                         {
    04958                             DeleteSelectionText();
    04959                             RaiseChangedEvent(this, true);
    04960                         }
    04961
    04962                         break;
    04963                     }
    04964
    04965                     // Ctrl-V Paste
    04966                     case 22:
    04967                     {
    04968                         PasteFromClipboard();
    04969                         RaiseChangedEvent(this, true);
    04970                         break;
    04971                     }
    04972                     case (int)System.Windows.Forms.Keys.Return:
    04973                         // Invoke the event when the user presses Enter.
    04974                         RaiseEnterEvent(this, true);
    04975                         break;
    04976
    04977                     // Ctrl-A Select All
    04978                     case 1:
    04979                     {
    04980                         if (textData.SelectionStart == caretPosition)
    04981                         {
    04982                             textData.SelectionStart = 0;
    04983                             PlaceCaret(textData.Text.Length);
    04984                         }
    04985                         break;
    04986                     }
    04987
    04988                     // Junk characters we don't want in the string
    04989                     case 26:  // Ctrl Z
    04990                     case 2:   // Ctrl B
    04991                     case 14:  // Ctrl N
    04992                     case 19:  // Ctrl S
    04993                     case 4:   // Ctrl D
    04994                     case 6:   // Ctrl F
    04995                     case 7:   // Ctrl G
    04996                     case 10:  // Ctrl J
    04997                     case 11:  // Ctrl K
    04998                     case 12:  // Ctrl L
    04999                     case 17:  // Ctrl Q
    05000                     case 23:  // Ctrl W
    05001                     case 5:   // Ctrl E
    05002                     case 18:  // Ctrl R
    05003                     case 20:  // Ctrl T
    05004                     case 25:  // Ctrl Y
    05005                     case 21:  // Ctrl U
    05006                     case 9:   // Ctrl I
    05007                     case 15:  // Ctrl O
    05008                     case 16:  // Ctrl P
    05009                     case 27:  // Ctrl [
    05010                     case 29:  // Ctrl ]
    05011                     case 28:  // Ctrl \
    05012                         break;
    05013
    05014                     default:
    05015                     {
    05016                         // If there's a selection and the user
    05017                         // starts to type, the selection should
    05018                         // be deleted.
    05019                         if (caretPosition != textData.SelectionStart)
    05020                         {
    05021                             DeleteSelectionText();
    05022                         }
    05023                         // If we are in overwrite mode and there is already
    05024                         // a char at the caret's position, simply replace it.
    05025                         // Otherwise, we insert the char as normal.
    05026                         if (!isInsertMode && caretPosition < textData.Text.Length)
    05027                         {
    05028                             // This isn't the most efficient way to do this, but it's simple
    05029                             // and shows the correct behavior
    05030                             char[] charData = textData.Text.ToCharArray();
    05031                             charData[caretPosition] = (char)wParam.ToInt32();
    05032                             textData.Text = new string(charData);
    05033                         }
    05034                         else
    05035                         {
    05036                             // Insert the char
    05037                             char c = (char)wParam.ToInt32();
    05038                             textData.Text = textData.Text.Insert(caretPosition, c.ToString());
    05039                         }
    05040
    05041                         // Move the caret and selection position now
    05042                         PlaceCaret(caretPosition + 1);
    05043                         textData.SelectionStart = caretPosition;
    05044                         FocusText();
    05045
    05046                         ResetCaretBlink();
    05047                         RaiseChangedEvent(this, true);
    05048                         break;
    05049                     }
    05050                 }
    05051             }
    05052             return false;
    05053         }
    05054
    05055
    05057         public override void Render(Device device, float elapsedTime)
    05058         {
    05059             if (!IsVisible)
    05060                 return; // Nothing to render
    05061
    05062             // Render the control graphics
    05063             for (int i = 0; i <= LowerRightBorder; ++i)
    05064             {
    05065                 Element e = elementList[i] as Element;
    05066                 e.TextureColor.Blend(ControlState.Normal,elapsedTime);
    05067                 parentDialog.DrawSprite(e, elementRects[i]);
    05068             }
    05069             //
    05070             // Compute the X coordinates of the first visible character.
    05071             //
    05072             int xFirst = textData.GetPositionFromCharIndex(firstVisible).X;
    05073             int xCaret = textData.GetPositionFromCharIndex(caretPosition).X;
    05074             int xSel;
    05075
    05076             if (caretPosition != textData.SelectionStart)
    05077                 xSel = textData.GetPositionFromCharIndex(textData.SelectionStart).X;
    05078             else
    05079                 xSel = xCaret;
    05080
    05081             // Render the selection rectangle
    05082             System.Drawing.Rectangle selRect = System.Drawing.Rectangle.Empty;
    05083             if (caretPosition != textData.SelectionStart)
    05084             {
    05085                 int selLeft = xCaret, selRight = xSel;
    05086                 // Swap if left is beigger than right
    05087                 if (selLeft > selRight)
    05088                 {
    05089                     int temp = selLeft;
    05090                     selLeft = selRight;
    05091                     selRight = temp;
    05092                 }
    05093                 selRect = System.Drawing.Rectangle.FromLTRB(
    05094                     selLeft, textRect.Top, selRight, textRect.Bottom);
    05095                 selRect.Offset(textRect.Left - xFirst, 0);
    05096                 selRect.Intersect(textRect);
    05097                 Parent.DrawRectangle(selRect, selectedBackColor);
    05098             }
    05099
    05100             // Render the text
    05101             Element textElement = elementList[TextLayer] as Element;
    05102             textElement.FontColor.Current = textColor;
    05103             parentDialog.DrawText(textData.Text.Substring(firstVisible), textElement, textRect);
    05104
    05105             // Render the selected text
    05106             if (caretPosition != textData.SelectionStart)
    05107             {
    05108                 int firstToRender = Math.Max(firstVisible, Math.Min(textData.SelectionStart, caretPosition));
    05109                 int numToRender = Math.Max(textData.SelectionStart, caretPosition) - firstToRender;
    05110                 textElement.FontColor.Current = selectedTextColor;
    05111                 parentDialog.DrawText(textData.Text.Substring(firstToRender, numToRender), textElement, selRect);
    05112             }
    05113
    05114             //
    05115             // Blink the caret
    05116             //
    05117             if(FrameworkTimer.GetAbsoluteTime() - lastBlink >= blinkTime)
    05118             {
    05119                 isCaretOn = !isCaretOn;
    05120                 lastBlink = FrameworkTimer.GetAbsoluteTime();
    05121             }
    05122
    05123             //
    05124             // Render the caret if this control has the focus
    05125             //
    05126             if( hasFocus && isCaretOn && !isHidingCaret )
    05127             {
    05128                 // Start the rectangle with insert mode caret
    05129                 System.Drawing.Rectangle caretRect = textRect;
    05130                 caretRect.Width = 2;
    05131                 caretRect.Location = new System.Drawing.Point(
    05132                     caretRect.Left - xFirst + xCaret -1,
    05133                     caretRect.Top);
    05134
    05135                 // If we are in overwrite mode, adjust the caret rectangle
    05136                 // to fill the entire character.
    05137                 if (!isInsertMode)
    05138                 {
    05139                     // Obtain the X coord of the current character
    05140                     caretRect.Width = 4;
    05141                 }
    05142
    05143                 parentDialog.DrawRectangle(caretRect, caretColor);
    05144             }
    05145
    05146         }
    05147     }
    05148 }