Author Topic: A Simple Dropdown List for Blocks  (Read 9897 times)

0 Members and 1 Guest are viewing this topic.

zoltan

  • Newt
  • Posts: 188
A Simple Dropdown List for Blocks
« on: June 30, 2012, 04:19:32 PM »
Here is an example of a simple dropdown list to display blocks.  You have to make sure that the BlockTableRecord has a preview icon either by opening the Design Center or using the BLOCKICON command.

This is in no way complete and not a good library component, but it is a quick example of what can be done.

huiz

  • Swamp Rat
  • Posts: 886
  • Certified Prof C3D
Re: A Simple Dropdown List for Blocks
« Reply #1 on: June 30, 2012, 04:52:29 PM »
Great example of the use of DrawString  8)

Very usable idea, thank you zoltan for sharing!
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

TheMaster

  • Guest
Re: A Simple Dropdown List for Blocks
« Reply #2 on: June 30, 2012, 07:10:48 PM »
Here is an example of a simple dropdown list to display blocks.  You have to make sure that the BlockTableRecord has a preview icon either by opening the Design Center or using the BLOCKICON command.

This is in no way complete and not a good library component, but it is a quick example of what can be done.

Your code works in a modal dialog but will probably crash AutoCAD or fail in some other way if you tried to use it in a modeless context (e.g., palette or a modeless form). You can't store BlockTableRecords in a control's items collections if you want the control to be usable in a modeless context.

I also don't like the idea of dedicated controls for things like block icons. They are just images. For example, my own controls are not dedicated to very specific AutoCAD objects, because there's quite a few cases where similar control functionality is needed (image and text), and I would not want to have to write a dedicated control for each specific use, so I use a generic combo box with support for an image/icon, which is easy to adapt to specific uses like block icons, linetype images, hatch patterns, etc. You can find lots of them on CodeProject.com.

« Last Edit: June 30, 2012, 07:18:53 PM by TheMaster »

zoltan

  • Newt
  • Posts: 188
Re: A Simple Dropdown List for Blocks
« Reply #3 on: June 30, 2012, 07:21:13 PM »

Your code works in a modal dialog but will probably crash AutoCAD or fail in some other way if you tried to use it in a modeless context (e.g., palette or a modeless form). You can't store BlockTableRecords in a control's items collections if you want the control to be usable in a modeless context.

That's why this is a simple example.

zoltan

  • Newt
  • Posts: 188
Re: A Simple Dropdown List for Blocks
« Reply #4 on: June 30, 2012, 07:23:04 PM »
Here is a SIMPLE layer list.  I would like to be able to make the controls inside the dropdown list be clickable and raise events, but that has proven to be pretty difficult in WinForms.  A piece-of-cake in WPF, from what I've read.


(Yes, the icons are crap.  I found them on the 'net. Feel free to replace them.)
« Last Edit: June 30, 2012, 07:51:10 PM by zoltan »

zoltan

  • Newt
  • Posts: 188
Re: A Simple Dropdown List for Blocks
« Reply #5 on: June 30, 2012, 07:54:47 PM »

I also don't like the idea of dedicated controls for things like block icons. They are just images. For example, my own controls are not dedicated to very specific AutoCAD objects, because there's quite a few cases where similar control functionality is needed (image and text), and I would not want to have to write a dedicated control for each specific use, so I use a generic combo box with support for an image/icon, which is easy to adapt to specific uses like block icons, linetype images, hatch patterns, etc. You can find lots of them on CodeProject.com.

Why would you not want to have a dedicated control for this?  I'm sure there are generic controls out there that you can put images and text into them in all sorts of flexible ways, but would it not be easier to have a control that is designed to draw the Block, Linetype, or Layer exactly the way it should be?  Where do you put the implementation to gather up all of the images and text for the Symbol Table Record and give it to your generic control in just the right formatting?



TheMaster

  • Guest
Re: A Simple Dropdown List for Blocks
« Reply #6 on: July 01, 2012, 12:58:55 AM »
Why would you not want to have a dedicated control for this? 
Because a dedicated control is not necessary, and doesn't promote separation of UI from business logic.

Today I need a combo box.  Tomorrow I may need a listbox, next week I may need a listview, treeview, etc..

Am I supposed to write (how many?) dedicated controls of different types for each circumstance?  Or, should I use generic controls, and put my business logic in a separate layer that can be easily reused by many different types of generic controls, and thereby avoid replication of the business logic.

Your example violates one of the most fundamental principles of good design, which is that it fails to separate business logic from the UI layer, and I'm not going to explain that in detail, because you can find plenty of discussion and explanation about that all over the internet.

So, it is not just one 'dedicated control', it is potentially many dedicated controls of different types.

If you hold a myopic view of the problem, you will only find yourself throwing code out and rewriting again many times over (or worse, copying and pasting it here and there) because you didn't anticipate future or varying requirements.

Quote
I'm sure there are generic controls out there that you can put images and text into them in all sorts of flexible ways, but would it not be easier to have a control that is designed to draw the Block, Linetype, or Layer exactly the way it should be? 

I can draw those things exactly the way they should drawn using well-designed generic controls. They're just bitmap images, nothing more special about them in that regards.

Quote
Where do you put the implementation to gather up all of the images and text for the Symbol Table Record and give it to your generic control in just the right formatting?

That question would seem to suggest that you've yet to discover data binding.

I'd suggest you research the concept of data binding, because it eliminates the need for dedicated code to 'gather up all the images and text', and also eliminates the need to manually load items into list-type controls as well, and makes the entire process generic. When you use data binding, the control itself gets the items to display in the control, and the data that is displayed for each item, with no code required on your part.

When you use data binding, you just give the control a data source that exposes a collection of the objects whose data will be displayed in each item in the control, and you give the control the names of the properties which the control will use to get the data from each item (e.g., the Name and BlockIcon properties of the BlockTableRecord would be the ones that would be used if one is directly binding to BlockTableRecord, which is not wise for reasons I cited earlier). 

The reason why data binding is preferred for providing data to the UI is because all types of controls support data binding to data sources in a consistent way, and that is what allows the same business logic to be re-used with any type of control that supports data binding, with no need for special or control-specific code.
« Last Edit: July 01, 2012, 01:35:26 AM by TheMaster »

TheMaster

  • Guest
Re: A Simple Dropdown List for Blocks
« Reply #7 on: July 01, 2012, 01:29:37 AM »

Your code works in a modal dialog but will probably crash AutoCAD or fail in some other way if you tried to use it in a modeless context (e.g., palette or a modeless form). You can't store BlockTableRecords in a control's items collections if you want the control to be usable in a modeless context.

That's why this is a simple example.

I don't think I can agree that designing a control that can't be used on anything but a model form qualifies as 'simple'.



zoltan

  • Newt
  • Posts: 188
Re: A Simple Dropdown List for Blocks
« Reply #8 on: July 01, 2012, 08:36:11 AM »
I don't think I can agree that designing a control that can't be used on anything but a model form qualifies as 'simple'.

Well, simple meaning that you just put it on a modal form, give it some BlockTableRecord or LayerTableRecord objects and it just works.  Creating a control like this that would work in a modeless context would require some complex logic to monitor the database and update the controls as the table records changed or update the list when records were added or removed, or the active document changed.  That implementation would be anything but simple.

I guess we just disagree on the definition of simple.

Maybe I should have used the word easy.  To get something done quickly, using myBlockComboBox.Items.Add(someBlockTableRecord) would be a lot easier than going out to CodeProject.com and finding some complicated control that somebody has designed to be very powerful and flexible, or purchasing a commercial product. Then, reading all about how it works and what it does before creating a code layer for separating the logic of displaying the information on the control.  And finally, creating a data binding between that control and some object which represents the data contained in the table records.

But I guess everybody's definition of easy is different.

TheMaster

  • Guest
Re: A Simple Dropdown List for Blocks
« Reply #9 on: July 01, 2012, 11:10:48 AM »
I don't think I can agree that designing a control that can't be used on anything but a model form qualifies as 'simple'.

Well, simple meaning that you just put it on a modal form, give it some BlockTableRecord or LayerTableRecord objects and it just works.  Creating a control like this that would work in a modeless context would require some complex logic to monitor the database and update the controls as the table records changed or update the list when records were added or removed, or the active document changed.  That implementation would be anything but simple.

I guess we just disagree on the definition of simple.

Maybe I should have used the word easy.  To get something done quickly, using myBlockComboBox.Items.Add(someBlockTableRecord) would be a lot easier than going out to CodeProject.com and finding some complicated control that somebody has designed to be very powerful and flexible, or purchasing a commercial product. Then, reading all about how it works and what it does before creating a code layer for separating the logic of displaying the information on the control.  And finally, creating a data binding between that control and some object which represents the data contained in the table records.

But I guess everybody's definition of easy is different.

If you're not familiar with things like data binding, then you don't know what 'easy' is, because data binding can make things even easier than what you've done, and without the horribly-bad practice of coupling business logic to the UI.

Perhaps after you've had to write more controls of different types that work in any context (modal or modeless), you might understand why doing things in what you consider to be the 'easy' way, but then ending up having to throw it out and redo it again from scratch (possibly more than once), is not the 'easy' way.

Beyond that, I'd prefer not to debate good/bad programming and design practices, as they are commonly-accepted ideas. If you think otherwise, post your code on StackOverflow.com or CodeProject.com and head for the nearest bunker  :laugh:
« Last Edit: July 01, 2012, 11:29:36 AM by TheMaster »

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: A Simple Dropdown List for Blocks
« Reply #10 on: July 02, 2012, 08:06:45 AM »
I have to agree with Tony on this one.  The "easier" way would be to use WPF and Data Binding your UI and seperating the "Model" in this case the Autocad DB.  I believe Autocad .NET has even exposed a bindable layer for both the events you show above but I have not tried using it.  Check Keans site I think he just wrote about it.

I use WPF for all my Autocad Palettes and Dialog Boxes now.  Usually just binding to an ObservableCollection and having my Business Logic just manipulate the collection.  It ends up that the logic doesnt care whats on the front end and the UI can be any TreeView, ListView, or Form it wants to be.
Revit 2019, AMEP 2019 64bit Win 10

TheMaster

  • Guest
Re: A Simple Dropdown List for Blocks
« Reply #11 on: July 02, 2012, 12:44:48 PM »

I guess we just disagree on the definition of simple.

Maybe I should have used the word easy.  To get something done quickly, using myBlockComboBox.Items.Add(someBlockTableRecord) would be a lot easier than going out to CodeProject.com and finding some complicated control that somebody has designed to be very powerful and flexible, or purchasing a commercial product. Then, reading all about how it works and what it does before creating a code layer for separating the logic of displaying the information on the control.  And finally, creating a data binding between that control and some object which represents the data contained in the table records.

But I guess everybody's definition of easy is different.

Yes, and everyone's definition of 'easy' is constrained by their experience and degree of familiarity with the tools they use.

Perhaps this little exercise might help you understand.

The exercise doesn't address images, but a simple extension of the standard WinForm's ComboBox could address that as well.

1.  Create a copy of the project you posted in this thread.

2.  Open the copy of the project, and delete your BlockComboBox from the form.

3.  Add a standard ComboBox to the form, and give it the name comboBox1

4.  Replace your form's constructor with this:

Code - C#: [Select]
  1.  
  2. public BlockForm(BlockTableRecord[] blocks)
  3. {
  4.     InitializeComponent();
  5.     this.comboBox1.DisplayMember = "Name";
  6.     this.comboBox1.DataSource = blocks;
  7. }
  8.  
  9.  

Run your project, and you'll see that with nothing more than two lines of code, the block names appear in a standard WinForms ComboBox.

The DisplayMember property value tells the combobox what property on the source item contains the text to be displayed in the dropdown list. A custom combobox that displays images along with text can utilize the very same method for getting the image from each item (by adding a property to the control that you can set to the name of the property that exposes the image on the item source object, and using Reflection to get its value from the items), and that would not require any dependence on any AutoCAD API, and could be reused for displaying any kind of items with images, rather than just blocks, and would require only one additional line of code to enable image display.

Once you've done the above, you will know what 'easy' is.

« Last Edit: July 02, 2012, 12:54:48 PM by TheMaster »

zoltan

  • Newt
  • Posts: 188
Re: A Simple Dropdown List for Blocks
« Reply #12 on: July 02, 2012, 03:11:41 PM »
Perhaps this little exercise might help you understand.

Yes. I understand now.  Can you show me how to make it display the preview image?

TheMaster

  • Guest
Re: A Simple Dropdown List for Blocks
« Reply #13 on: July 02, 2012, 05:31:33 PM »
Perhaps this little exercise might help you understand.

Yes. I understand now.  Can you show me how to make it display the preview image?

If you mean how to write a generic combobox with image support that
uses data binding to get the item images, you would add a property to
the custom combobox that you set to the name of the property on the
item source object that exposes the image, and you can access it from
your OnDrawItem() override like this:

Code - C#: [Select]
  1.  
  2. // Assign the name of the property on the item source
  3. // object that holds the Image for the item, which for
  4. // a BlockTableRecord, would be "PreviewIcon":
  5.  
  6. public string ImageMember {get;set;}
  7.  
  8. // Call this to get the image for the item. You could
  9. // (and probably should) cache the image so that it
  10. // doesn't need to be fetched every time you need to
  11. // draw it.  You could use an ImageList to cache the
  12. // images for each item, keyed to the item's name.
  13.  
  14. System.Drawing.Image GetItemImage( object item )
  15. {
  16.   if( string.IsNullOrEmpty( this.ImageMember ) )
  17.     throw new InvalidOperationException("ImageMember property not assigned");
  18.   PropertyInfo pi = item.GetType().GetProperty( this.ImageMember );
  19.   if( pi == null )
  20.     throw new InvalidOperationException("Property not found on item source");
  21.   return pi.GetValue( item, null ) as System.Drawing.Image;
  22. }
  23.  
  24.  

Another thing you need to correct is that your custom combobox control
handles the DrawItem event, which is not how derived types implement
custom drawing. Events are meant to be handled by other consumers but
not by derived types. Derived types should override the corresponding
virtual member, which in this case is the OnDrawItem() method.
« Last Edit: July 02, 2012, 07:23:42 PM by TheMaster »

TheMaster

  • Guest
Re: A Simple Dropdown List for Blocks
« Reply #14 on: July 02, 2012, 07:55:24 PM »
Here is a SIMPLE layer list.  I would like to be able to make the controls inside the dropdown list be clickable and raise events, but that has proven to be pretty difficult in WinForms.  A piece-of-cake in WPF, from what I've read.


(Yes, the icons are crap.  I found them on the 'net. Feel free to replace them.)

Making the items clickable essentially requires that you handle the mouse events and use the location to determine what item the mouse was over, there's not much more to it than that. As long as you know the size of the images, and each one's origin in control coordinates, it shouldn't be hard to figure out which one was clicked.


zoltan

  • Newt
  • Posts: 188
Re: A Simple Dropdown List for Blocks
« Reply #15 on: July 03, 2012, 07:28:41 AM »
Making the items clickable essentially requires that you handle the mouse events and use the location to determine what item the mouse was over, there's not much more to it than that. As long as you know the size of the images, and each one's origin in control coordinates, it shouldn't be hard to figure out which one was clicked.

Yes, That was my idea too.  I have tried it in a number of exhaustive ways.  It turns out that the mouse events are only raised for the control when it is rolled up and there are no mouse events when the list is dropped down.

Another thing you need to correct is that your custom combobox control
handles the DrawItem event, which is not how derived types implement
custom drawing. Events are meant to be handled by other consumers but
not by derived types. Derived types should override the corresponding
virtual member, which in this case is the OnDrawItem() method.

Yes.  Very good point.  I overlooked that in haste.
« Last Edit: July 03, 2012, 07:32:13 AM by zoltan »

TheMaster

  • Guest
Re: A Simple Dropdown List for Blocks
« Reply #16 on: July 03, 2012, 01:10:27 PM »
Making the items clickable essentially requires that you handle the mouse events and use the location to determine what item the mouse was over, there's not much more to it than that. As long as you know the size of the images, and each one's origin in control coordinates, it shouldn't be hard to figure out which one was clicked.

Yes, That was my idea too.  I have tried it in a number of exhaustive ways.  It turns out that the mouse events are only raised for the control when it is rolled up and there are no mouse events when the list is dropped down.


Are you sure?  From looking at the framework code, it would appear that OnMouseDown(), OnMouseMove(), etc. are being called.



zoltan

  • Newt
  • Posts: 188
Re: A Simple Dropdown List for Blocks
« Reply #17 on: July 03, 2012, 01:43:44 PM »
Are you sure?  From looking at the framework code, it would appear that OnMouseDown(), OnMouseMove(), etc. are being called.

Where are you looking in the framework?

I put this in the control:
Code - C#: [Select]
  1. protected override void OnMouseDown(MouseEventArgs e)
  2. {
  3.    Debug.WriteLine(e.Location);
  4.   base.OnMouseDown(e);
  5. }
  6.  

It does not return a point when clicking on a dropdown list item.  Are you seeing different behavior?

Jeff H

  • Needs a day job
  • Posts: 6103
Re: A Simple Dropdown List for Blocks
« Reply #18 on: July 03, 2012, 02:42:08 PM »
Am I missing something which is usually the case but for a combo box would'nt you just use a SelectionChange Event index or value?
 
 

Jeff H

  • Needs a day job
  • Posts: 6103
Re: A Simple Dropdown List for Blocks
« Reply #19 on: July 03, 2012, 03:00:16 PM »
Am I missing something which is usually the case but for a combo box would'nt you just use a SelectionChange Event index or value?
I see what your talking about.
 
 

TheMaster

  • Guest
Re: A Simple Dropdown List for Blocks
« Reply #20 on: July 04, 2012, 01:31:19 AM »
Are you sure?  From looking at the framework code, it would appear that OnMouseDown(), OnMouseMove(), etc. are being called.

Where are you looking in the framework?

I put this in the control:
Code - C#: [Select]
  1. protected override void OnMouseDown(MouseEventArgs e)
  2. {
  3.    Debug.WriteLine(e.Location);
  4.   base.OnMouseDown(e);
  5. }
  6.  

It does not return a point when clicking on a dropdown list item.  Are you seeing different behavior?

Are you trying to get notified when you click on an item in the dropdown list, or in the control's edit box?

Cloning AutoCAD's layer combo is not trivial, and you're not going to do it by simply subclassing a combobox and handling a few events. The default behavior for a ComboBox is to close the dropdown when the user clicks on an item in it.  The dropdown on AutoCAD's layer combo doesn't close when the user clicks an item, and you're not going to emulate that behavior easily.

I don't recall ever needing a layer combo box, but I have used a ListView to display layers and their states using icons in the same style as the layer combo.


MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: A Simple Dropdown List for Blocks
« Reply #21 on: July 05, 2012, 08:07:14 AM »
Just want to point out that now might be a good time for you to look into WPF.  All the problems you're having are easily addressed in WPF including cloning the behavior of AutoCADs dropdown listbox for layers, although I haven't tried it yet.  A WPF listbox has both a Click event and a SelectionChanged event you could hook into either depending on how you want to handle user actions.
Revit 2019, AMEP 2019 64bit Win 10

Jeff H

  • Needs a day job
  • Posts: 6103
Re: A Simple Dropdown List for Blocks
« Reply #22 on: July 08, 2012, 11:06:59 AM »
Thanks for sharing Zoltan.
 
I thought had something laying around kinda similar, but nothing great or special, and not a good implementation for reuse, but could use it to kinda mimic the layer combobox on the properties palette.
 
One of the issues with it is that one of properties the of the object that you bind it to needs to be a System.Drawing.Color that you set the ComboBox.ValueMember to or all the boxes will be black.
 

 
I could not find it but off of memory for binding it
Code - C#: [Select]
  1.             comboBoxColor.DataSource = colors;
  2.             comboBoxColor.ValueMember = "Color";
  3.             comboBoxColor.DisplayMember = "Name";
  4.  

 
Then basically a hard-coded version of OnDrawItem
Code - C#: [Select]
  1.         protected override void OnDrawItem(DrawItemEventArgs e)
  2.         {
  3.             e.DrawBackground();
  4.             if (e.Index > -1)
  5.             {
  6.                 object obj = this.Items[e.Index];
  7.                 object objValue = obj.GetType().GetProperty(this.ValueMember).GetGetMethod().Invoke(obj, null);
  8.                 string dispalyMember = obj.GetType().GetProperty(this.DisplayMember).GetValue(obj, null).ToString();
  9.  
  10.                 Color fillColor = objValue is Color ? (Color)objValue : Color.Black;
  11.                 Rectangle colorRectangle = new Rectangle(e.Bounds.X  + 1, e.Bounds.Y +  2, 9, 9);
  12.  
  13.                 using (Brush brush = new SolidBrush(fillColor))
  14.                 {
  15.                     e.Graphics.FillRectangle(brush, colorRectangle);
  16.                     e.Graphics.DrawRectangle(Pens.Black, colorRectangle);
  17.                 }
  18.  
  19.                 using (Brush brush = new SolidBrush(e.ForeColor))
  20.                 {
  21.                     e.Graphics.DrawString(dispalyMember, e.Font, brush, colorRectangle.Right  + 2, e.Bounds.Top);
  22.                 }
  23.  
  24.                 e.DrawFocusRectangle();
  25.             }
  26.         }
  27.  

When I first did I tried something like this where I added some public properties so set box height and width, text offset, etc..... in VS designer.
Code - C#: [Select]
  1.   public partial class ColorComboBox : ComboBox
  2.     {
  3.         private System.ComponentModel.IContainer components = null;
  4.         public Pen RectangleBorderColor { get; set; }
  5.         public Color RectangleFillColor { get; set; }
  6.         public int RectangleWidth { get; set; }
  7.         public int RectangleHeight { get; set; }
  8.         public int RectangleXOffset { get; set; }
  9.         public int RectangleYOffset { get; set; }
  10.         public int TextXOffset { get; set; }
  11.         public int TextYOffset { get; set; }
  12.         public ColorComboBox()
  13.         {
  14.             InitializeComponent();
  15.             RectangleBorderColor = Pens.Black;
  16.             RectangleFillColor = Color.White;
  17.             RectangleHeight = this.Height / 2;
  18.             RectangleWidth = RectangleHeight;
  19.             RectangleXOffset = this.Width % RectangleWidth;
  20.             RectangleYOffset = this.Height % RectangleHeight;
  21.             TextXOffset = RectangleWidth / 2;
  22.             TextYOffset = 0;
  23.         }
  24.        
  25.               /// <summary>
  26.         /// Clean up any resources being used.
  27.         /// </summary>
  28.         /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
  29.         protected override void Dispose(bool disposing)
  30.         {
  31.             if (disposing && (components != null))
  32.             {
  33.                 components.Dispose();
  34.             }
  35.             base.Dispose(disposing);
  36.         }  
  37.         /// <summary>
  38.         /// Required method for Designer support - do not modify
  39.         /// the contents of this method with the code editor.
  40.         /// </summary>
  41.         private void InitializeComponent()
  42.         {
  43.             components = new System.ComponentModel.Container();
  44.         }
  45.         protected override void OnCreateControl()
  46.         {
  47.             base.OnCreateControl();
  48.             this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
  49.             this.DropDownStyle = ComboBoxStyle.DropDownList;
  50.         }
  51.         protected override void OnDrawItem(DrawItemEventArgs e)
  52.         {
  53.             e.DrawBackground();
  54.             if (e.Index > -1)
  55.             {
  56.                 object obj = this.Items[e.Index];
  57.                 object objValue = obj.GetType().GetProperty(this.ValueMember).GetGetMethod().Invoke(obj, null);
  58.                 string dispalyMember = obj.GetType().GetProperty(this.DisplayMember).GetValue(obj, null).ToString();
  59.                 Color fillColor = objValue is Color ? (Color)objValue : RectangleFillColor;
  60.  
  61.                 int width = RectangleWidth > e.Bounds.Width ? e.Bounds.Width : RectangleWidth;
  62.                 int height = RectangleHeight > e.Bounds.Height ? e.Bounds.Height : RectangleHeight;
  63.  
  64.                 int xOffset = RectangleXOffset > e.Bounds.Width - width ? e.Bounds.Width - width : RectangleXOffset;
  65.                 int yOffset = RectangleYOffset > e.Bounds.Height - height ? e.Bounds.Height - height : RectangleYOffset;
  66.  
  67.                 Rectangle colorRectangle = new Rectangle(e.Bounds.X + xOffset, e.Bounds.Y +  yOffset, width, height);
  68.  
  69.                 using (Brush brush = new SolidBrush(fillColor))
  70.                 {
  71.                     e.Graphics.FillRectangle(brush, colorRectangle);
  72.                     e.Graphics.DrawRectangle(Pens.Black, colorRectangle);
  73.                 }
  74.  
  75.                 using (Brush brush = new SolidBrush(e.ForeColor))
  76.                 {
  77.                     e.Graphics.DrawString(dispalyMember, e.Font, brush, colorRectangle.Right  + TextXOffset, e.Bounds.Top  + TextYOffset);
  78.                 }
  79.  
  80.                 e.DrawFocusRectangle();
  81.             }
  82.         }
  83.     }
  84.  

 
 
 
 
« Last Edit: July 08, 2012, 11:19:54 AM by Jeff H »

zoltan

  • Newt
  • Posts: 188
Re: A Simple Dropdown List for Blocks
« Reply #23 on: July 08, 2012, 12:27:09 PM »
That is very cool, Jeff.  I was about to make a ColorComboBox as well, but I got off track.

If you bind it to Autodesk.AutoCAD.Colors.Color, your ValueMember would be ColorValue and the DisplayMember property would be ColorName.  It should work for ACI colors, True Color, and Color Book colors.
« Last Edit: July 08, 2012, 12:32:28 PM by zoltan »

Jeff H

  • Needs a day job
  • Posts: 6103
Re: A Simple Dropdown List for Blocks
« Reply #24 on: July 08, 2012, 01:02:27 PM »
A wrote a little class for testing it quickly and knew it useless and was wasting my time and was not really needed but you just made me realize how really useless and how much I really wasted my time writing it. :ugly:
 
 
This website looks familiar and I think I picked up the basic idea from here
http://alinberce.wordpress.com/2009/05/14/custom-combo-box-with-colors-and-text-part-ii/
 
Another issue I noticed is if another control event, or just changing the color value of the object in the bound collection that is the SelectedValue or current item in combobox the color would update 1, 2, 3, or sometimes 4 seconds later but probably is a method that can be used to update it immediately.

Jeff H

  • Needs a day job
  • Posts: 6103
Re: A Simple Dropdown List for Blocks
« Reply #25 on: July 08, 2012, 01:58:03 PM »
That is very cool, Jeff.  I was about to make a ColorComboBox as well, but I got off track.

If you bind it to Autodesk.AutoCAD.Colors.Color, your ValueMember would be ColorValue and the DisplayMember property would be ColorName.  It should work for ACI colors, True Color, and Color Book colors.

Not sure the difference and might not work in other situations but little testing I did looks like Color.ColorNameForDisplay should be used.

Jeff H

  • Needs a day job
  • Posts: 6103
Re: A Simple Dropdown List for Blocks
« Reply #26 on: July 08, 2012, 05:45:37 PM »
Another issue I noticed is if another control event, or just changing the color value of the object in the bound collection that is the SelectedValue or current item in combobox the color would update 1, 2, 3, or sometimes 4 seconds later but probably is a method that can be used to update it immediately.
Not sure if best way but ComboBox.Refresh() seems to work