- Main Page
- Packages
- Classes
- Files

- File List
- File Members

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

Go to the documentation of this file.

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