Anda di halaman 1dari 386

Welcome to the Windows Forms FAQ.

Questions and answers in this FAQ have been collected


from newsgroup posts, various mailing lists and the employees of Syncfusion. I have tried to mention the
source wherever possible. If you think that you should be credited for an answer, please send me a note
and I will be happy to add a credit mention.

If you have a FAQ, or any other good Windows Forms resource, please email me. The Windows Forms
FAQ forum is available if you need more information.

Windows Forms
Deployment
Controls
Books
Data Binding
Datagrid
Docking
Keyboard Handling
Layout
Licensing
Menus
Mouse Handling
from MFC from VB6
Patterns
Printing
Resources
Scrolling
Tips
Common Dialogs
ListBox
ComboBox
RichTextBox
ListView
TreeView Button
TabControl
TextBox
Cursors
WebBrowser
ProgressBars
PictureBox
Form
CheckedListBox
MDI
In IE
Smart Client

GDI+
Bitmaps & Images
Fonts
GDI+Colors
Books Brushes
Drawing Tips
Hit Testing
from GDI Paths & Regions
Pens
Rendering Primitives

Interoperability
Win32 Books COM

Tools
Other FAQs Resource Editor Metadata Viewers

Design Time
Serialization
Custom Designers Tips
Type Editors UI

VS.NET
Tips Debugging Macros

Framework Tips
General
Events
Performance
CGI General IO
Strings
1.1 Threading
XML
Math

Network
Tips

1. Windows Forms Deployment

1.1 How can I run an EXE from within my application?


1.2 What are the common issues in redirecting assemblies using the publisher policy files?
1.3 How can I find all programs with a GUI (not just arbitrary windows) that are running on my local
machine?
1.4 How can I get a list of all processes running on my system?
1.5 How can I make sure there is only one instance of my application running?
1.6 How do I determine which operating system is running?
1.7 How can I get all IP addresses for my local machine?
1.8 My user does not have .NET installed. Will he be able to run my Windows Forms application?
1.9 How do I get the path to my running EXE?
1.10 How can I programmatically obtain the name of the assembly that the code is executing in ?
1.11 How can I see what is installed in the Global Assembly on a machine?
1.12 How do I set the company name that is returned by
System.Windows.Forms.Application.CompanyName?

2. Windows Forms Controls

2.1 How do you prevent serialization of certain child controls in your Composite Control?
2.2 How do I get hold of the currently focused Control?
2.3 Why do calling Focus() on a control not set focus on it?
2.4 How do I listen to windows messages in my Control?
2.5 How do I programatically change the color of a control?
2.6 How can I change the Border color of my control?
2.7 Why should I provide a Non-Client border to my Control derived class?
2.8 How do I provide a 2 pixel 3d border in the Non-Client area of my Control derived class?
2.9 How do I provide a 1 pixel border in the NonClient area of my Control?
2.10 How do I invalidate a control including it's NonClient area?
2.11 How can I implement a scrollable picture box?
2.12 How can I put Controls, a ProgressBar for example, into a StatusBar?
2.13 How do I implement an ownerdrawn statusbar so I can put a progressbar in it?
2.14 How would I change the icon that appears on the toolbox for a custom control?
2.15 A control's Validating event is hit even when the user clicks on the Close box. How can I avoid this
behavior?
2.16 I would like to prevent validation in my textbox when the user clicks on my Cancel button, how do
I do this?
2.17 Why does adding images to an ImageList in the designer cause them to lose their alpha channel?
2.18 Why do the XP Icons when drawn using Graphics.DrawImage not draw transparently?
2.19 Why do the XP Icons that have alpha channel not draw properly when associated with controls like
ListView?
2.20 How do I prevent resizing of my Controls by the user, via Docking or anchoring or manual resizing
during design-time?
2.21 What control do I use to insert Separator lines between Controls in my Dialog?
2.22 How can I make my controls transparent so the form's background image can show through them?
2.23 How do I create an editable listbox with an in-place TextBox and Button?
2.24 How do I determine the width/height of the Non-Client area (like the border in a textbox) of a
Control?
2.25 How can I programmatically manipulate Anchor styles?
2.26 What is the best method to override in custom Controls to perform custom initialization during
runtime?
2.27 I set a Control's Visible property to true and in the immediate next statement, it returns false. Why
doesn't setting the Visible property 'take'?
2.28 I'm trying to make the background of my linklabel transparent so a picturebox will show through it.
However, if I set the link label's BackColor property to Transparent the label still has a white background.
Why?
2.29 How do I dynamically load a control from a DLL?
2.30 What is the (DynamicProperties) item listed on a control's property page in VS.NET?
2.31 How can I make a Panel or Label semi-transparent on a Windows Form?
2.32 How can I add a control to a Window Form at runtime?
2.33 How do I make the arrow keys be accepted by a control (such as a button) and not handled
automatically by the framework's focus management?
2.34 In the property browser for a custom control, how do I disable a property initially, but enable it
later based on some other property changing?
2.35 How can I have the control designer create the custom editor by calling the constructor with the
additional parameters rather than the default constructor?
2.36 How do I listen to the screen resolution change in my control?
2.37 How do I determine which button in a Toolbar is clicked?

3. Windows Forms Books

3.1 Windows Forms Programming in C#?


3.2 Programming Microsoft Windows with C#?
3.3 C# Design Patterns?

4. Windows Forms Data Binding

4.1 Does MySql work with ADO.NET?


4.2 Where can I find a discussion of databinding and windows forms?
4.3 How do I test for a null value in DataView.RowFilter?
4.4 I don't have SQL Server. Is there any way to run the samples that need SQL server?
4.5 How can I programmatically move through a dataset that has bound controls?
4.6 When I try to update a dataset I get an error that the system is unable to find "Table"?
4.7 How can I bind an ArrayList to a DataGrid?
4.8 When I try to bind two comboboxes to the same datatable, both boxes show the same values,
changing one changes the other. How do I make them have distinct values?
4.9 How do I bind a mdb file to a datagrid?
4.10 How do I bind a listbox or a combobox to a MDB file?
4.11 In my databound ComboBox, how do I set the SelectedItem property?
4.12 Are server side cursors supported in .NET?
4.13 I am populating a ListBox by binding it to an ArrayList. The initial display is OK, but later changes
to my ArrayList are not shown in my ListBox. How can I get the changes to show properly?
4.14 My SQL server runs on a non-default port. How can I specify this port in my connection string?
4.15 What is a DataSet?
4.16 How do I add updating support to a dataset?
4.17 How can I import a CSV file into a DataTable?
4.18 How can I prevent a ComboBox and DataGrid bound to the same DataTable from sharing the same
current position?
4.19 I get a 'This would cause two bindings in the collection to bind to the same property' error message.
What might cause this?
4.20 How do I bind a TextBox to a nested relation?
4.21 How do I call a SQL stored procedure?
4.22 I programatically change a bound TextBox value, but the value does not get pushed back into the
bound datasource. How can I make sure the DataSource is updated?
4.23 Why does the CheckedListBox lose checked state when placed in a tab page that gets hidded and
shown?

5. Windows Forms Datagrid

5.1 How can I programatically set the rowheight of a row in my DataGrid?


5.2 How can I autosize the rowheights in my datagrid?
5.3 How do I prevent sorting a single column in my DataGrid?
5.4 How do I programmatically select a row in DataGrid?
5.5 How can I translate a point to a cell in the datagrid?
5.6 I lost the settings in my DataGrid set during design-time?
5.7 How do I prevent a click into the grid highlighting a cell?
5.8 How do I prevent the datagrid from displaying its append row (the row at the end with an asterisk)?
5.9 How can I put a combobox in a column of a datagrid?
5.10 How can I catch a double-click into a column header cell?
5.11 How can I select the entire row when the user clicks on a cell in the row?
5.12 How can I get text from a column header in a MouseUp event?
5.13 How do I hide a column?
5.14 How do I color a individual cell depending upon its value or some external method?
5.15 How can I put a checkbox in a column of my DataGrid?
5.16 How can I restrict the keystrokes that will be accepted in a column of my datagrid?
5.17 How do I make a field auto increment as new rows are added to my datagrid?
5.18 How can I prevent a particular cell from being editable?
5.19 How do I move columns in a datagrid?
5.20 How can I do cell by cell validation in a datagrid?
5.21 How do I programmatically determine the selected rows in a datagrid?
5.22 How can I move rows by dragging the row header cell?
5.23 I want to do custom handling of special keys such as the Tab key or F2 in the TextBox of a column
in the DataGrid. How do I subclass this TextBox to get at it virtual members?
5.24 How can I have a column of icons in my datagrid?
5.25 How can I tell if the current row has changed and whether I am on the AddNew row or not?
5.26 How do I hide the gridlines or set them to a particular color?
5.27 How can I get the selected text in an active gridcell?
5.28 How do I determine whether a checkbox in my datagrid is checked or not?
5.29 How can I bind the datagrid to a datasource without using any wizards?
5.30 How can I bind two datagrids in a Master-Detail relationship?
5.31 How do I get the row or column that has been clicked on?
5.32 How do I add an unbound column to my bound datagrid?
5.33 How do I get the row and column of the current cell in my datagrid?
5.34 How can I prevent the Enter key from moving to the next cell when the user is actively editing the
cell and presses Enter?
5.35 How do I set the width of a column in my DataGrid?
5.36 How can I implement OLE Drag & Drop between a DataGrid and another OLE DnD object that
supports the Text format?
5.37 How can I make my DataGrid support a single select mode, and not the default multiselect mode?
5.38 How can I get celltips or tooltips to vary from cell to cell in my DataGrid?
5.39 How can I get notification of the changing of a value in a column of comboboxes within my
datagrid?
5.40 How can I make the datagrid have no currentcell?
5.41 How can I make my grid never have an active edit cell and always select whole rows (as in a
browser-type grid)?
5.42 I have hidden (column width = 0) columns on the right side of my datagrid, but tabbing does not
work properly. How can I get tabbing to work?
5.43 How can I get the number of rows in my DataGrid?
5.44 How do I format a date column in a datagrid?
5.45 How can I change the width of the row headers or hide them?
5.46 How do I catch a doubleclick in my datagrid?
5.47 How can I make my last column wide enough to exactly occupy all the client area of the datagrid?
5.48 How can I prevent my user from sizing columns in my datagrid?
5.49 How can I catch the bool values changing in a DataGridBoolColumn?
5.50 When I click on a row header, the row is selected and no cell is active. How can I do this
programmatically?
5.51 How can I force the vertical scrollbar in my DataGrid to always be visible?
5.52 How can I autosize a column in my datagrid?
5.53 How can I get rid of the error icon that appears when there is an editing error?
5.54 How do I find the top-left visible cell in a datagrid?
5.55 I want to display negative values with a CR suffix, instead of a minus sign. How can I perform
custom formatting on the cells in my datagrid?
5.56 I want to do sort of a database join of two tables. How can I use data from two DataTables in a
single DataGrid?
5.57 How do I display a column of buttons such as pushbuttons or combobox buttons?
5.58 How can I put up a confirmation question when the user tries to delete a row in the datagrid by
clicking on the row header and pressing the Delete key?
5.59 How can I enable column selections in my datagrid?
5.60 How do I programmatically scroll the datagrid to a particular row?
5.61 How can I place text in the rowheader column of my datagrid?
5.62 How do I set default values for new rows in my datagrid?
5.63 How do I iterate through all the rows and columns in my datagrid?
5.64 How can I specially color only the currentcell of my readonly datagrid?
5.65 How can I make the Enter Key behave like the Tab Key and move to the next cell?
5.66 How do I use the DataColumn.Expression property to add a computed/combined column to my
datagrid?
5.67 How can I change the font used in a grid cell on a cell by cell or row by row basis?
5.68 How can I use a mouse to select cell ranges in my datagrid?
5.69 How can I control the cursor over my DataGrid?
5.70 How can I programatically add and remove columns in my DataGrid without modifying the
DataTable datasource?
5.71 How can I have a column of bitmaps in a DataGrid?
5.72 How can I add my custom columnstyles to the designer so I can use them in my DataGrid at design
time?
5.73 After scrolling with the mouse wheel on a selected row in a DataGrid I cannot get it back into view.
Is there a work around?
5.74 How can I make the DataGrid column be blank and not display (null) as the default value?
5.75 How can I add a DateTimePicker column style to the DataGrid?
5.76 How do I determine the DataGridTableStyle MappingName that should used for a DataGrid to
make sure the grid uses my tablestyle?
5.77 I have a derived DataGridColumnStyle. From within my Paint override, how can I get at other
values in the DataGrid?
5.78 How do I retrieve the current row from a DataTable bound to a DataGrid after the grid has been
sorted?
5.79 How can I catch when the user clicks off the grid, say to close the form?
5.80 How can I get a CheckBox column in a DataGrid to react to the first click?
5.81 How can I use events to restrict key input to grid cells?
5.82 How can I format columns in my DataGrid without explicilty adding DataGridColumnStyles?
5.83 How can I auto-adjust keyboard input? For example, make typing 12312002 be taken as a valid
date, 12/31/2002.
5.84 Can I display the rows in my datagrid in a free-form layout using textboxes on a panel?
5.85 How can I tell whether a scrollbar is visible in my DataGrid is visible?
5.86 How do I autosize the columns in my DataGrid so they always fill the the grid's client area?
5.87 How can I prevent all the cells in my DataGrid from being edited without deriving
GridColumnStyle?
5.88 How can I prevent the plus-minus icon that appears next to the row header when I have a datagrid
displayed bound to a datasource that has a relation defined?
5.89 How can I display master-details-details in three separate grids?
5.90 In my datagrid, if I press tab to enter a column using a derived columnstyle, the column does not
receive focus. Why?
5.91 How can I detect when a cell starts being edited, not when it becomes current?

6. Windows Forms Docking

6.1 How can I make a control occupy all the client area of a form?
6.2 How can I make my control automatically grow when the parent form is sized?
6.3 What is the difference between a form's Anchor property and a form's Dock property?

7. Windows Forms Keyboard Handling

7.1 How can I prevent a control from getting a particular keystroke?


7.2 How can I tell if an ALT, Shift or CTL key is pressed without catching an event?
7.3 How do I check the state of the virtual keys, Caps lock for example?
7.4 How can I simulate keyboard input in my application?
7.5 How can I catch keyboard messages on a application-wide basis?
7.6 How can I listen for certain keys at the Form level irrespective of which Control has the focus?

8. Windows Forms Layout

8.1 How can I programmatically set the initial position of a Form so that it is displayed properly after
calling ShowDialog()?
8.2 How do I create a custom layout engine?
8.3 I have a form with several controls on it. As I size the form, the controls are being resized
continuously. Is it possible to postpone changing the controls position until the resizing is complete?

9. Windows Forms Licensing

9.1 How does .NET support licensing?


9.2 How do I find the file version of an EXE?

10. Windows Forms Menus

10.1 How do I clone menus, insert menus, use popup menus, etc.
10.2 How do I add a context menu to a control?
10.3 When using the ContextMenu on multiple Controls, how do I know on which Control the right
click was performed?
10.4 How do menu shortcuts work?
10.5 How do I make the context menu appear only when clicked at certain portions of the Control?
10.6 How do I prevent the context menu from showing up on certain keyboard keys (like Keys.Apps)?
10.7 How do I know when a menu is closed/started so that I can refresh my status bar?
10.8 Is there an Idle event which will get fired from which I could update my menu item's enabled state?
10.9 How do I cancel a context menu programatically?
10.10 Is there an easy way to create the "Window" menu that shows the list of child forms open?
10.11 How can I work around my menu shortcuts from showing up incorrectly when I use
Ctrl+Number?
10.12 How do I control the position of the context menu when it is invoked via the keyboard?
10.13 How do I disable the default context menu of a textbox?
10.14 How can I make the context menu to close after a set time interval?
10.15 How can I add an icon to my menu items?
10.16 How to add a Separator in a menu?
10.17 How can I enable the mnemonics (underline) to show when my application is launched?

11. Windows Forms Mouse Handling

11.1 How can I resize a borderless form with a rubber-band effect?


11.2 How do I get a mouse cursor position in my control's client coordinates?
11.3 How can I catch the mouse being over a control?
11.4 How do I set the mouse cursor position?
11.5 How can I reset the OnMouseHover timer so that it will fire again without the mouse having to
leave the client area of a control?
11.6 How can I drag a window if it doesn't have a title bar or border?
11.7 How can I determine if a mouse button is pressed and moving over my form?
11.8 Why am I not receiving MouseLeave messages in a Control in my Form?

12. Windows Forms from MFC

12.1 As a VC++ programmer, what should I look out for when using C#?
12.2 Where can I find a succinct discussion of Windows Forms?
12.3 When I add a destructor to a class, why isn't it hit when my instantiated object goes out of scope?
12.4 How do I convert a string to a double or int? What plays the role of atof and atoi in C#?
12.5 What class or method do I use to retrieve system metrics like the width of a scrollbar?
12.6 In C++, the code "MyClass ht;" creates an object ht on the stack frame. But in C#, this same code
compiles, but gives a runtime error. Why?
12.7 I need to encode the LParam argument of a mouse message. How do I do MakeLong , HiWord and
LoWord type conversions?
12.8 How do you clear the contents of a list box?

13. Windows Forms from VB6

13.1 How do I draw a line in VB7 as there is no Line command as there was in VB6?
13.2 What is the replacement for VB6's SendKeys statement?
13.3 In VB6, I used control arrays to have a common handler handle events from several controls. How
can I do this in Windows Forms?
13.4 What is different about working with forms in VB.NET? For example, how can I reference one
form from another form?

14. Windows Forms Patterns

14.1 How to display a status dialog in a background thread during a long operation and alow the user to
cancel?
14.2 How can I throw my events asynchronously?
14.3 Why are the Tooltips not being shown on a NumericUpDown control?
14.4 How to get the hyperlink and the hyperlink text dragged from IE in my Control's drag-drop event?
15. Windows Forms Printing

15.1 How do I print a form?


15.2 How do I display the PrintPreview maximized and control its zooming?

16. Windows Forms Resources

16.1 What are the steps to compiling and using multiple language resources?
16.2 How do I load a BMP file that has been added to my solution as an embedded resource?
16.3 Why doesn't a Form containing an ImageList not open in WinRes?
16.4 Where can I find information on globalization?
16.5 How do I read embedded resources?
16.6 How can I check if a certain resource is included in a assembly?
16.7 How can I save a temporary disk file from an embedded string resource?
16.8 How do I embed a manifest file into my exe?
16.9 How do I read or write resources from code?
16.10 How do I create resources to make culture-aware programs without re-compiling code?
16.11 How do I programmatically use resources to make my programs culturely aware?
16.12 How can I dynamically load a resource file?

17. Windows Forms Scrolling

17.1 How do I add support for custom scrolling to my own user control?
17.2 Are there any events that get fired when the user scrolls?

18. Windows Forms Tips

18.1 How do I write a screen saver?


18.2 How do I determine the screen resolution?
18.3 How do I determine the working area of a screen without the systemtray area?
18.4 How do I position my form to the bottom right of the screen when it opens up the first time above
the system tray?
18.5 How do I change my screen's resolution programatically?
18.6 How do I determine the current date/time?
18.7 How do I determine the time taken for a long operation that I perform?
18.8 What are the implications of using the Timer class in System.Timers as opposed to the Timer class
in System.Windows.Forms?
18.9 Is there an easy way to Create/Delete/Move files in the Windows File System?
18.10 How can I use XP Themes with Windows Forms using the .NET FrameWork 1.1?
18.11 How can I use XP Themes with Windows Forms using the .NET FrameWork 1.0?
18.12 How do I use Windows Forms Controls in Internet Explorer?
18.13 Are event handlers required to have this signature void MyEventHandler(object sender, EventArgs
e)?
18.14 How do I change a directory name?
18.15 How do I beep the computer's speaker in a Windows Form application?
18.16 How do I use the system clipboard?
18.17 How do I add an application to the Window's Tray?
18.18 Why would I be getting a NullReferenceException in Windows Forms with no application code in
the call stack?
18.19 When I try to catch the Resize event to handle sizing of MDI children, the event is called even
before my form's constructor can create the children throwing an exception. How do I avoid this?
18.20 How can I tell if the user has changed some system preference such as the locale or display
settings?
18.21 What mechanisms does .Net provide to convert one type to another?
18.22 Its possible that some of my class members will not be initialized when one of my virtual
members gets called even before the constructor. How can I avoid this?
18.23 In a Hashtable, why doesn't setting the value for an existing key to be null remove the key from
the Hashtable?
18.24 How do I create windows shortcuts on my desktop programatically in .Net?
18.25 How can I add a custom verb to the file and folder context menus in the explorer shell?
18.26 Can working on WinForms and .Net in general get exciting?
18.27 I have a long loop. How can I make my application continue to process events while it is
executing this loop?
18.28 How can I display HTML in a Form?
18.29 The MessageBox always appears in the center of the screen. How can I change it's location?
18.30 If I have a button with &Next as the text, the N-accelerator key does not appear until I press Alt.
Why?
18.31 How can I shut down/restart the OS from my Windows Forms Application?
18.32 I get a message 'DragDrop registration' failed. Why?
18.33 What is the purpose of the [STA Thread] attribute for the Main method of a C# program?
18.34 I add my application to the Window's Tray, set ShowInTaskBar to false, but the program still
appears in the Alt+Tab list.

19. Windows Forms Common Dialogs

19.1 How do I use the ColorDialog to pick a color?


19.2 How do I use the FontDialog class to set a control's font?
19.3 How do I implement a Folder Browser class?
19.4 How can I get just the name of a file from the complete path string?
19.5 How can I get just the extension of a file from the complete path string?
19.6 How do I use the OpenFileDialog?
19.7 How do I specify the path for the FolderBrowser instance when it opens the first time?

20. Windows Forms ListBox

20.1 How do I add and delete items from a ListBox?


20.2 How do I implement Drag and Drop support between ListBoxes?
20.3 How can I drag file names from Windows Explorer and drop them into a listbox?
20.4 How do I implement an ownerdrawn listbox?
20.5 How can I set the width of a listbox to fit the text?

21. Windows Forms ComboBox

21.1 How do I bind the values of an enum to a ComboBox?


21.2 How can I programmatically prevent the combobox from dropping?
21.3 How can I turn off editing in the textbox portion of a ComboBox, restricting the user to selecting
only those options in the drop list?
21.4 How can I adjust the height of the of my ComboBox dropdown?
21.5 How do I implement an owner drawn combobox?
21.6 How do I add a ComboBox button to a toolbar?
21.7 How do I set the width of a combobox to fit the entries in its list?
21.8 How can I programmatically create a new list for my ComboBox dropdown?
22. Windows Forms RichTextBox

22.1 How can I create and save a RTF file?


22.2 How can I get a string that contains RTF format codes into a RichTextBox?
22.3 How do I make the RichTextBox support drag and drop?
22.4 How do I set the color and font in a RichEditBox?
22.5 How can I change the FontStyle of a selection without losing the styles that are present?
22.6 How can I programmatically position the cursor on a given line and character of my richtextbox?
22.7 How can I load an embedded rich text file into a richtextbox?
22.8 How can I print my rich text?
22.9 Where can I find more information on the RTF specification?
22.10 How can I add a hyperlink to a RichTextBox control?

23. Windows Forms ListView

23.1 How do I add SubItems to a ListView control?


23.2 When I call ListViewItem.Selected = true;, why doesn't the item get selected?
23.3 How do I unselect the selected items in a ListView programatically?
23.4 I am trying to programmatically change the ForeColor and BackColor properties of subitems in a
listview. Why doesn't this work?
23.5 How do I implement custom column sorting in a listview?
23.6 How do I programmatically select an item in my listview?
23.7 How can I sort a column in a ListView?
23.8 How can I implement an owner drawn listview?
23.9 How can I tell which column (subitem) has been clicked on in my listview?

24. Windows Forms TreeView

24.1 How do I implement Drag and Drop support between two TreeViews?
24.2 How do I make the TreeView scroll when I drag an item to the top or bottom?
24.3 How do I display checkboxes in the nodes of a treeview?
24.4 When I right-click a tree node, it does not become selected. How can I make it be selected on a
right-click?
24.5 When I get the SelectedNode in the treeview's Click event, it is the old selection. How do I get the
newly selected node?
24.6 How can I get a tooltip to vary from node to node in my treeview?
24.7 How can I determine the node level of a node in my treeview?
24.8 How can I populate a TreeView Control with XML Data?
24.9 How can I clone/copy all the nodes from one TreeView Control to another?
24.10 How do I programmatically select a node in a TreeView control?
24.11 Can I select multiple nodes in a TreeView Control?
24.12 How can I display a context menu when the user right-clicks on a node in the TreeView control?
24.13 How can I ensure that a node is selected when the user clicks along the line of a node?

25. Windows Forms Button

25.1 How do I autosize a button to fit its text?


25.2 How can I decorate a button face with custom drawing?
25.3 How can I put a bitmap or icon on a button face?
25.4 How can I trigger a button click event?
25.5 How can I get button to fire a click event at specific time intervals while the mouse is down like a
scrollbar button?

26. Windows Forms TabControl

26.1 How do color the tabs on my TabControl?


26.2 How do I programatically select a Tab Page?
26.3 Why do the order of the tabs keep changing when opening and closing the Form?
26.4 How do I force the focus to be on a text box in a tab page when the application gets loaded?
26.5 For a TabControl, how do I make the tabs on the tab pages appear on the bottom instead of on the
right?
26.6 How do I use code to insert or delete tabpages in a TabControl?
26.7 How do I dynamically hide/unhide tabs in a TabControl?
26.8 How do I prevent the user from changing the selected tab page?
26.9 How can I drag and drop TabPages between TabControls?

27. Windows Forms TextBox

27.1 How can I prevent the beep when enter is hit in textbox?
27.2 How do I disable pasting into a TextBox (via Ctrl + V and the context menu)?
27.3 How can I disable the right-click context menu in my textbox?
27.4 How do I format numbers, dates and currencies in a TextBox?
27.5 How do I browse for, and read a text file into an TextBox?
27.6 How do I send a EM_XXXX message to a textbox to get some value such as line index in C#?
27.7 How do I prevent a control from receiving focus when it receives a mouseclick?
27.8 How do I make my textbox use all upper (or lower) case characters?
27.9 I have a delete key shortcut for my main menu. When my textbox is being edited, pressing delete
activates this menu items instead of being processed by the TextBox. How can I get my TextBox to handle
this delete?
27.10 How can I use a TextBox to enter a password?
27.11 How can I place a TextBox in overwrite mode instead of insert mode?
27.12 How can I make a ReadOnly TextBox ignore the mousedowns so that you cannot scroll the text or
set the cursor?
27.13 How can I restrict the characters that my textbox can accept?
27.14 How do I set several lines into a multiline textbox?
27.15 When I set a TextBox to Readonly or set Enabled to false, the text color is gray. How can I force it
to be the color specified in the ForeColor property of the TextBox.
27.16 How can I make the focus move to the next control when the user presses the Enter key in a
TextBox?

28. Windows Forms Cursors

28.1 I set the wait cursor using Cursor.Current = Cursors.WaitCursor;. Why does does it disappear
before I want it to?
28.2 How do I change the cursor for a control?
28.3 How to convert a Cursor class to a .cur file?
28.4 How to load and display a cursor from a resource manifest?

29. Windows Forms WebBrowser

29.1 How can I host a WebBrowser control in a Windows Form?


29.2 How can I enable editing for the WebBrowser?
29.3 How can I catch the BeforeNavigate2 event?
29.4 WebBrowser control does not seem to be cleaning up temp files. How can this be done?
29.5 How can I use MSHTML to edit HTML in a Windows Forms control?

30. Windows Forms ProgressBars

30.1 How can I implement a smooth ProgressBar?

31. Windows Forms PictureBox

31.1 How can I place a border around a PictureBox?


31.2 How can I copy a bitmap from the clipboard to a PictureBox?
31.3 How can I copy and paste images/graphs etc from MS Office to a PictureBox?
31.4 How can I drag and drop an image from one PictureBox to another?

32. Windows Forms Form

32.1 How can I programmatically maximize or minimize a form?


32.2 How can I display a pop up a confirmation dialog when the user closes the form?
32.3 How can I center my form?
32.4 How do I prevent users from resizing a form?
32.5 How do I programmatically set an image as Form's Icon ?
32.6 How can I add items to the System Menu of a form.
32.7 How can I have a form with no title bar, but yet keep the resizing borders?
32.8 I don't want to have the Close box on my form's title bar. How do I remove this system menu box?
32.9 How do I change my application's icon?
32.10 How can I tell if a form is closed from the controlbox (system menu) or from a call to
Form.Close?
32.11 I have two forms. How can I access a textbox on one form from the other form?
32.12 How do I create a non-modal top level form that always stays on top of all the app's windows (like
the VS.Net find dialog)?
32.13 How can I display a form that is 'TopMost' for only my application, but not other applications?
32.14 How do I automatically resize the Form when the screen resolution changes between design-time
and runtime?
32.15 How can I ensure that my form will always be on the desktop?
32.16 How can I restrict or control the size of my form?
32.17 How can I prevent a form from being shown in the taskbar?
32.18 How do I prevent a user from moving a form at run time?
32.19 How can I create a non rectangular form?
32.20 How can I make my form cover the whole screen including the TaskBar?
32.21 How can I move a Borderless form?
32.22 How do I force a Windows Form application to exit?
32.23 How do I set the default button for a form?
32.24 How do I get an HWND for a form?
32.25 How can I detect if the user clicks into another window from my modal dialog?
32.26 How do I create a form with no border?
32.27 How do I prevent a Form from closing when the user clicks on the close button on the form's
system menu?
32.28 How do I display a splash screen type form, one with only client area (no border or titlebar)?
32.29 How do I get the window handle (HWND) of my form or control?
32.30 How can I make sure I don't open a second instance modeless dialog that is already opened from
my main form?
32.31 Is there a way to halt a screen from painting until all the controls on the form are initialized?
32.32 How do I return values from a form?
32.33 How can I easily manage whether controls on my form are readonly or not?
32.34 The controls that I've try to add to my form at runtime don't show up. What's wrong?
32.35 Setting Form.Visible to false does not make my main form start up invisibly. How can I make my
main form start up invisibly?
32.36 How to make a form transparent?
32.37 How can I create an instance of a Form class just from knowing its name in a string?

33. Windows Forms CheckedListBox

33.1 How do I check/uncheck all items in my checkedlist?

34. Windows Forms MDI

34.1 How can I create an MDI application in the .NET framework with C#?
34.2 I have an MDI application with several child forms. The child form's Activated event is not being
fired consistently as different child forms are activated. What's wrong?
34.3 In an MDI application, the MDI child's MaximumSize and MinimumSize properties don't seem to
take effect. How can I restrict the size of my MDI child?
34.4 How do I check to see if a child form is already displayed so I don't have two instances showing?
34.5 I need to perform certain custom processing whenever an MDI child form is added to/removed
from the MDIContainer form. How do I determine this?
34.6 How do I paint in my mdi container, a logo, for example?
34.7 How do I make my child Form fill the entire mdi client without being maximized?
34.8 How can I change the background of my MDI Client container?

35. Windows Forms In IE

35.1 Where can I get information on hosting Windows Forms Controls in IE?
35.2 How do I clear the download cache in my client machine?
35.3 How can I use a WinForms Control in IE?
35.4 What are some common gotchas while trying to embed a Windows Forms Control in IE?
35.5 What are some common UI limitations while running code in the Internet Zone?

36. Windows Forms Smart Client

36.1 Where are the getting started info. on Smart Client Deployment?

37. GDI+ Bitmaps & Images

37.1 How do I create a "Negative" representation of my image?


37.2 How do I programmatically load, modify and save a bitmap?
37.3 How do I draw an image with a gray scale?
37.4 How do I draw my bitmap in a disabled state?
37.5 How can I programmatically create a bitmap?
37.6 How can I swap colors in a bitmap or icon?
37.7 How do I create a new image off a base image with certain portions of the base image modified, in
code?
37.8 How do I extract a Bitmap from an icon of a specific size?
37.9 How to draw a shadow for a given transparent image?
37.10 How to draw a faded image?
37.11 How do I overlay one bitmap over another?
37.12 How do I get the color of a pixel in my bitmap?
37.13 How do I capture a bitmap of my form?
37.14 How can I create a thumbnail of a bitmap?
37.15 How do I create a new bitmap with a new size based on an existing bitmap?
37.16 How can I read individual frames from an animated image?

38. GDI+ Fonts

38.1 How do I set the font for a control?


38.2 When I try to set a particular font style, say italics, I get an error message "Property cannot be
assigned to -- it is read only". How can I set this read only property?
38.3 How can I draw font samples from the available fonts?
38.4 MeasureString seems to have problems with white space and punctuation. Is there a better method
to use?
38.5 How can I draw a single line of text with different fonts using DrawString?
38.6 How do I display adjacent text?
38.7 How can I fill a combobox with available fonts?

39. GDI+Colors

39.1 I need to save a color as a string and be able to retrieve it. How can I do this?
39.2 How do I convert a color to integer and vice-versa?
39.3 How do I desaturate a specific color?
39.4 How do you translate a HSB color to RGB?
39.5 Is there a way to force some contrast between two colors (like background color and foreground
color)?
39.6 What is alpha blending?
39.7 Is there a way to find out the brightness of a Color?
39.8 How can a translate an OLE_COLOR into a GDI+ Color object?

40. GDI+ Books

40.1 GDI+ Programming: Creating Custom Controls using C#?


40.2 Programming Windows with C#?

41. GDI+ Brushes

41.1 How do I use hatched and gradient brush types?


41.2 How to set the rendering origin for hatch brushes?
41.3 How to create my own hatch styles for brushes?

42. GDI+ Drawing Tips

42.1 Where can I see a basic tutorial on GDI+?


42.2 What are some things to remember when drawing in Window Forms?
42.3 When can I not use AutoScrolling? In other words why would I ever need any other form of
autoscrolling?
42.4 Are AutoScrolling bounds setup in World or Device coordinates?
42.5 Why am I not being able to set a Color.Transparent color as a background to my control?
42.6 Why does a Control not draw transparent even after setting it's BackColor to Transparent?
42.7 How can I get the screen resolution of my display?
42.8 How do I draw rotated text?
42.9 Why does my transparent Panel whose parent has a gradient background flicker a lot when resized?
42.10 How do I get a count of the gdi handles currently in use in my application?
42.11 How can I minimize flickering when drawing a control?
42.12 How do I draw circles, rectangles, lines and text?
42.13 How do I get a snapshot of my desktop?
42.14 How can I draw without handling a paint message?

43. GDI+ Hit Testing

43.1 How to HitTest a polygonal region?

44. GDI+ from GDI

44.1 How does text drawing differ between GDI+ and GDI?
44.2 How do I do XOR-type-drawing (SetROP2-Function in MFC) in GDI+?
44.3 Can I mix GDI and GDI+ drawing in my application?
44.4 How do the Win32 System Colors map to the colors provided by System.Drawing.SystemColors?

45. GDI+ Paths & Regions

45.1 What is a GraphicsPath?


45.2 How can I create non-rectangular windows?
45.3 Is there a imagemap like control in Windows Forms?

46. GDI+ Pens

46.1 Using a wide pen, how do I draw a series of line segments with rounded corners?
46.2 With a wide pen, how can I control how the endpoints of my line appear?

47. GDI+ Rendering Primitives

48. Interoperability Win32

48.1 How to add an extern reference to a Win32 API?


48.2 How do I hit a web page from within a button handler in my Windows Forms application?
48.3 How can I capture output from an arbitary console application from within my Window Form
application?
48.4 How do I convert LParam in a message from IntPtr to the Win32 type?
48.5 How do I maximize my main window?
48.6 How can I use 'Hooks' in .NET?
48.7 Is there any way to get to the Edit control or the editHandle of a ComboBox using safe code?
48.8 How do I get the associated Icon from a file in the file system?
48.9 How can I get the directory name for "My Documents" folder and other system directories?
48.10 How can I show a form without making it active?
48.11 How to access a winapi that has a LPTSTR and maxlen param?
48.12 How do I use an exported function (extern "C") from a legacy DLL?
48.13 How can I draw outside my WIndow?
48.14 Is there any way to get detailed error information for Win32 errors when using Platform Invoke?

49. Interoperability Books

49.1 Are there any books out there that focus on COM interop?

50. Interoperability COM

50.1 How do you invoke a COM Class in a specific COM DLL in .Net?
50.2 How do you dynamically invoke a COM class from its GUID?
50.3 How do you make .Net components that could be used by COM?
50.4 How can I read and display Excel files from within my C# application?
50.5 Should I try to use Interoperability or migration to use COM with .NET?
50.6 How can I get events fired by an Office XP chart control hosted in my Windows Forms app?

51. Tools Other FAQs

51.1 Are there any easy to use Unit Testing frameworks available for .NET applications?
51.2 Are there any easy to use build tools for .NET applications?
51.3 Are there tools available for generatiing class library documentation for .NET applications?
51.4 How can I generate PDF files from my .NET application?
51.5 CVS integration using C#?
51.6 How can I read and write zip files in my Windows Forms program.

52. Tools Resource Editor

52.1 I don't like the resource Editor that comes with Visual Studio.NET. Are there any alternatives out
there?

53. Tools Metadata Viewers

53.1 Are there any tools that allow me to view the rich meta data that .NET assemblies have? Is there a
OLEVIEW equivalent for .NET?
53.2 How do I disassemble a .net assembly (dll/exe) into the IL format?
53.3 How do I create a dll/exe off a previously diassembled .il file?
53.4 How can I launch ILDASM from the VS.NET 2003 IDE?

54. Design Time Serialization

54.1 How to make my Component add itself to the contained Form's IContainer list?
54.2 How do I prevent the default values of my Localized properties form being set?
54.3 How do I force the changes in base class fields to be serialized via a base class property in the
inherited type's designer?

55. Design Time Custom Designers

55.1 How do I implement a custom designer?


55.2 I have created a usercontrol and a designer, How can i debug the designer?
55.3 How can I insert custom menu items (verbs) into my Component/Control designer's Context Menu
in design time?
55.4 How do I control the state of my custom verb in my designer?
55.5 How do I restrict my Container Control to parent only certain types of Controls, and vice-versa,
during design-time?
55.6 How do I prevent the Designer-Grid from being drawn on my Container Control during design-
time?
55.7 How do I get Mouse Messages on my Control during design-time?
55.8 Can I do some custom drawing on my control designer's surface during design-time?
55.9 How can I know when a Control/Component has been selected in the designer surface?
55.10 How do I prevent resizing of my Control in the designer?

56. Design Time Tips

56.1 When a property gets modified, how do you refresh other properties of a Component/Control in the
property browser?
56.2 How to Reinitialize extender provider dependencies (the logic within CanExtend) from within the
designer?
56.3 How do you detect the designer host getting loaded for the first time in your designer?
56.4 How do you provide "dynamic" default values?
56.5 How to debug your design time code (like designers, typeconverters, etc.)?
56.6 How do you make your custom data types property browser browsable when contained in a
Control/Component (as a property)?
56.7 How to make properties in your custom data type appear in a particular order in the property
browser?
56.8 How do I provide Intellisense support to my controls while coding against them and also provide
Description support for the properties in the property grid?
56.9 How do I change the Zorder of my docked windows at design time?
56.10 How can I tell my form is being used in design time and not runtime?
56.11 How can I persist a collection of items into code?
56.12 How can I supply a list of values to be chosen from a dropdown list at runtime for a specific type
similar to enums?
56.13 How to serialize properties of items that do not implement IComponent in a collection?
56.14 What is the function of TypeDescriptor?
56.15 What is the function of TypeConverters?
56.16 How do I make my custom dialog droppable in the design surface like a component?
56.17 How do I prevent my Component from becoming visible in the VS.Net Toolbox?

57. Design Time Type Editors

57.1 In my UITypeEditor for a collection, how do I change the "(collection)" string to a string of my
own?
57.2 How can I allow my user to add more than 1 type of object to my collection, during design-time?
57.3 How can I let the user edit my Multi-Dimensional collection?
57.4 What should I do to make my StringCollection property editable during design-time?
57.5 From within a PropertyGrid, is there any way to display property names that differ from the actual
class property names?
57.6 How do I make a class expandable within the property browser?
57.7 How can I paint a represenation of enum values using a UITypeEditor?

58. Design Time UI


58.1 How do you prevent certain Controls from appearing in the property browser during designtime?
58.2 At designtime, how can I hide a base class property in my derived control from the user?
58.3 How do I add a custom tab to the property grid when it is displaying my object's properties?
58.4 How do I prevent my Control's properties from getting combined with properties belonging to
other objects in a Properties window?
58.5 How do I make some properties not browsable in the designer, but browsable in the editor?

59. VS.NET Tips

59.1 Is there any easy way to convert C# code to VB.NET?


59.2 Is there any easy way to convert VB.NET code to C#?
59.3 How can I word-wrap the Tooltip that is dispayed?
59.4 How do I add a tooltip to my Button control?
59.5 How can I have a multiline tooltip?
59.6 How do I use VS to add an override for a virtual member of a baseclass?
59.7 How do I compile unsafe code in VS.NET?
59.8 How to convert an application project to class library project, and vice versa?
59.9 How do I start Visual Studio.NET from the command line?
59.10 What are the options with using Visual Studio.NET from the command line?
59.11 How do I create and use a component?
59.12 In Visual Studio, all my docking windows are out of whack. How can I reset them so things will
be docked properly?
59.13 How do I move a docked control around (or change the dock order) in my Form?
59.14 How can I instruct the compiler to use the Main method in Class2 instead of Class1?
59.15 Whenever I share files between projects it appears that Visual Studio.NET copies the files over
into the new project. I want to just share the file and not have it copied over. Is there any way to do this?
59.16 How can I graphically set the tab order for controls on a form?
59.17 How can I speed up my work in Visual Studio?
59.18 I have code snippets that I use often. How can I manage them so I can easily used them?
59.19 Can I drag and drop code snippets using the VS.NET IDE?
59.20 In VS.NET, how can I change the build order of projects in my solution?
59.21 In VS.NET, how can I specify the start up project for my application?
59.22 If I create an assembly, how can I see the assembly/components from with the VS.Net "Add..."
dialogs?
59.23 How does VS.Net find the referenced assemblies when I build a project from the command line?
59.24 How can I get the default namespace of a C# project in VS.NET?
59.25 How can I open a project created with Visual Studio .NET 2003 in Visual Studio .NET 2002?
59.26 How can I change the Word Wrap Property of VS.NET IDE?

60. VS.NET Debugging

60.1 How can I see debug/trace statements when I run my application in debug mode?
60.2 Can I trace the caught Exception without breaking into the debugger?
60.3 How do I conditionally include certain methods based on some preprocessor defines?
60.4 What is fuslogvw.exe?
60.5 How do I set the debugger to Break on Exception?
60.6 If I have a user control and a designer, how can I debug the designer?
60.7 How can I use the debugger paint and focus problems as the stops are always hit too early?
60.8 In a debug build, how do I write debug information to the output window (similar to the TRACE
macro from VC6)?
60.9 Why am I getting dupllicate trace messages for my trace statements?
60.10 How can I direct debug output to a text file?
60.11 Can I trace the Call Stack at any particular point without breaking into the debugger?

61. VS.NET Macros

61.1 Can VB.NET code be formatted using macros?


61.2 Is it possible to call macros as part of a Visual Studio.NET command line build (or from a batch
file)?

62. Framework Tips General

62.1 How can I catch an exception on a program wide basis?


62.2 Can I generate UML diagrams from C# code?
62.3 Is it possible to turn off strong name validation for an assembly?
62.4 Does .Net support "deprication" as in Java?
62.5 Is there any way to Shutdown/Restart Windows using .NET?
62.6 Can .NET applications run on non Microsoft Platforms?
62.7 Can I play audio and video files using .NET?
62.8 Can I create file associations with .NET?
62.9 How can I Invoke a private interface implementations of an instance using reflection?
62.10 How can I adjust the version number for multiple projects without changing every
AssemblyInfo.cs file constantly?
62.11 How do I launch IE or any other process from code?
62.12 How do I pre-JIT an assembly to native code during installation?
62.13 How do I get the install directory for the version of the runtime that is loaded in the current
process?
62.14 How to retrieve the assembly version, name, etc. contained in the "AssemblyInfo.cs", from inside
the running app?
62.15 Is there a way to access private and protected members of a class instance?
62.16 In VB.NET how do I access the runtime type object of a specified type from it's type name?
62.17 How do I print a doument using .NET?

63. Framework Tips Events

63.1 How do I intercept event subscription of a event in my base class?


63.2 How do I control the order in which events are fired to multiple subscribers?
63.3 How do I figure out if a particular client object has susbcribed to one of my events?

64. Framework Tips Performance

64.1 Is it possible to cache an assembly to improve performance?


64.2 Why are .Net programs slow to load when running under a domain?

65. Framework Tips CGI

65.1 Can I write CGI applications using .NET?

66. Framework Tips General IO

66.1 How do you persist any object in the registry?


66.2 How can I listen to changes in a file/directory in the windows file system?
66.3 How can I convert a long path to a short path?
66.4 I want to iterate through both files and folders in a given folder. Is this possible?
66.5 My application requires a simple ini file. Is there a easy way to implement this without using any
parsing?
66.6 How can I access a webpage from a windows form?
66.7 I just want to read a text file into a string. Is there some simple code for this?
66.8 I just want to write a simple text file. Is there some simple code for this?
66.9 While deserializing how do I check whether a name is available in the deserialized info?
66.10 How come some of the objects are not initialized during deserialization?

67. Framework Tips Strings

67.1 How to I introduce culture information into formatted strings?


67.2 How do I convert a string to an double or int?
67.3 How can I convert the string "Red" into the color Color.Red, and vice versa?
67.4 Is there a .Net way of deciding whether a string is numeric or not?
67.5 How can I determine if a string is a valid date?
67.6 How can I convert an Enumeration member to string and vice-versa?
67.7 My program dynamically builds lots of strings. Is there a way to optimize string performance?
67.8 I hate string processing. Is there an easier way to do string manipulation?
67.9 How do I use the CSV clipboard format supported by Excel?
67.10 Is there a easy way to test Regular Expressions?

68. Framework Tips 1.1

68.1 What's new in the 1.1 framework?


68.2 Is EnableVisualStyles method to support XP styles in my app broken?
68.3 How come I don't get to see the full call stack while debugging in VS2003?

69. Framework Tips Threading

69.1 Why do I have to use the STAThread attribute for my main method in my app.?
69.2 When I close my application, my secondary thread does not exit.
69.3 I call invoke Abort on my threads, but they still do not terminate.

70. Framework Tips XML

70.1 How do I add an XmlNode from one XmlDocument to an XmlNode in another XmlDocument?

71. Framework Tips Math

71.1 Are there any libraries to do numerical analysis with .NET?

72. Network Tips

72.1 How do I access an FTP server using .NET?


72.2 How do I send email using .NET?
72.3 How do I read email from a POP server using .NET?
72.4 I want to UUENCODE and decode data? Does the .NET framework have support for this?
72.5 Is there a way to Ping servers using .NET?
72.6 Is there a easy way to add Socks Proxy support?
72.7 Is there a easy way to query Whois information?

© 2001-06 Copyright George Shepherd.

1. Windows Forms Deployment FAQ Home


1.1 How can I run an EXE from within my application?
1.2 What are the common issues in redirecting assemblies using the publisher policy files?
1.3 How can I find all programs with a GUI (not just arbitrary windows) that are running on my local
machine?
1.4 How can I get a list of all processes running on my system?
1.5 How can I make sure there is only one instance of my application running?
1.6 How do I determine which operating system is running?
1.7 How can I get all IP addresses for my local machine?
1.8 My user does not have .NET installed. Will he be able to run my Windows Forms application?
1.9 How do I get the path to my running EXE?
1.10 How can I programmatically obtain the name of the assembly that the code is executing in ?
1.11 How can I see what is installed in the Global Assembly on a machine?
1.12 How do I set the company name that is returned by
System.Windows.Forms.Application.CompanyName?

1.1 How can I run an EXE from within my application?

Use the Process class found in the System.Diagnostics namespace.

[C#]
Process proc = new Process();

proc.StartInfo.FileName = @"Notepad.exe";
proc.StartInfo.Arguments = "";
proc.Start();

[VB.NET]
Dim proc As New Process()

proc.StartInfo.FileName = "Notepad.exe"
proc.StartInfo.Arguments = ""
proc.Start()

1.2 What are the common issues in redirecting assemblies using the publisher policy files?
1) Make sure to follow proper naming conventions for the policy dll. For example, if the original assembly
name is TestAssembly.dll then the corresponding policy assembly should be called
"policy.1.0.TestAssembly.dll" to make this redirection work for all "1.0.*" version bindings of the original
assembly.

2) While specifying the name for the assembly in the policy file, do not include the ".dll" extension.

This is wrong:

>assemblyIdentity name="TestAssembly.dll" publicKeyToken="f638d0a8d5996dd4" culture="neutral" /<

Instead use:

>assemblyIdentity name="TestAssembly" publicKeyToken="f638d0a8d5996dd4" culture="neutral" /<

3) Make sure to sign the policy assembly with the same strong name as the original.

4) Make sure to distribute the policy file along with the policy assembly. Installing the policy assembly in
the GAC alone will not suffice. Note that any change made to the policy file after creating the policy
assembly will not take effect.

5) Always use /link (to the policy file) in the "al" command while creating the policy assembly. Do not use
/embed. It doesn't seem to be supported.

Some good links:

http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/cpguide/html/cpconcreatingpublisherpolicyfile.asp

http://www.newtelligence.com/downloads/downloads-basta2001.aspx

http://www.only4gurus.com/DotNet/studies/managevers.htm

1.3 How can I find all programs with a GUI (not just arbitrary windows) that are running on my
local machine?

You could use EnumWindows with p/Invoke, but using the static Process.GetProcesses() found in the
System.Diagnostics namespace will avoid the interop overhead.

[C#]
Using System.Diagnostics;
...
foreach ( Process p in Process.GetProcesses(System.Environment.MachineName) )
{
if( p.MainWindowHandle != IntPtr.Zero)
{
//this is a GUI app
Console.WriteLine( p ); // string s = p.ToString();
}
}

[VB.NET]
Imports System.Diagnostics
...
Dim p As Process
For Each p In Process.GetProcesses(System.Environment.MachineName)
If p.MainWindowHandle <> IntPtr.Zero Then
'this is a GUI app
Console.WriteLine(p) ' string s = p.ToString();
End If
Next p

There is one potential problem on Windows 98. If a process was started with
ProcessStartInfo.UseShellExecute set to true, this MainWindowHandle is not available.

1.4 How can I get a list of all processes running on my system?

Use the static Process.GetProcesses() found in the System.Diagnostics namespace.

[C#]
Using System.Diagnostics;
...
foreach ( Process p in Process.GetProcesses() )
Console.WriteLine( p ); // string s = p.ToString();

[VB.NET]
Imports System.Diagnostics
...
Dim p As Process
For Each p In Process.GetProcesses()
Console.WriteLine(p) ' string s = p.ToString()
Next p

1.5 How can I make sure there is only one instance of my application running?

Saar Carmi shows how to do this in his sample found on C# Corner. In it, he uses the Process class in
System.Diagnostics to implement this functionality using code such as

[C#]
public static Process RunningInstance()
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName (current.ProcessName);

//Loop through the running processes in with the same name


foreach (Process process in processes)
{
//Ignore the current process
if (process.Id != current.Id)
{
//Make sure that the process is running from the exe file.
if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") ==
current.MainModule.FileName)
{
//Return the other process instance.
return process;
}
}
}
//No other instance was found, return null.
return null;
}

[VB.NET]
Public Shared Function RunningInstance() As Process
Dim current As Process = Process.GetCurrentProcess()
Dim processes As Process() = Process.GetProcessesByName(current.ProcessName)

'Loop through the running processes in with the same name


Dim process As Process
For Each process In processes
'Ignore the current process
If process.Id <> current.Id Then
'Make sure that the process is running from the exe file.
If [Assembly].GetExecutingAssembly().Location.Replace("/", "\") =
current.MainModule.FileName Then
'Return the other process instance.
Return process
End If
End If
Next process
'No other instance was found, return null.
Return Nothing
End Function 'RunningInstance

1.6 How do I determine which operating system is running?

The Environment class in the System namespace has this information.

[C#]
string versionText = Environment.OSVersion.Version.ToString();

[VB.NET]
Dim versionText As String = Environment.OSVersion.Version.ToString()
The Version property has member properties such as Major and Minor that give additional information.

Note that XP is windows version 5.1

1.7 How can I get all IP addresses for my local machine?

[C#]
string s ="";

System.Net.IPAddress[] addressList = Dns.GetHostByName(Dns.GetHostName()).AddressList;

for (int i = 0; i < addressList.Length; i ++)


{
s += addressList[i].ToString() + "\n";
}

textBox1.Text = s;

[VB.NET]
Dim s As String = ""

Dim addressList As System.Net.IPAddress() = Dns.GetHostByName(Dns.GetHostName()).AddressList

Dim i As Integer
For i = 0 To addressList.Length - 1
s += addressList(i).ToString() + ControlChars.Lf
Next i

textBox1.Text = s

1.8 My user does not have .NET installed. Will he be able to run my Windows Forms application?

No, the .NET runtime platform has to be on any machine that will run your Windows Forms application.
Microsoft has made the .NET runtime platform installation (dotnetredist.exe) available as a free download
from Microsoft .NET Framework Redistributable .

1.9 How do I get the path to my running EXE?

The Application class has a static member ExecutablePath that has this information.

[C#]
textBox1.Text = Application.ExecutablePath;

[VB.NET]
TextBox1.Text = Application.ExecutablePath
1.10 How can I programmatically obtain the name of the assembly that the code is executing in ?

The following code snippet demonstrates how you can obtain the name of the assembly that the code is
executing in:

[C#]
MessageBox.Show(System.Reflection.Assembly.GetEntryAssembly().GetName().Name);

[VB.NET]
MessageBox.Show(System.Reflection.Assembly.GetEnTryAssembly().GetName().Name)

1.11 How can I see what is installed in the Global Assembly on a machine?

Use Windows Explorer to view the C:\WINNT\assembly folder. If the .NET Framework is installed, the
Windows Explorer will show a custom view of this folder. Use the detailed view to see the details of each
assembly.

1.12 How do I set the company name that is returned by


System.Windows.Forms.Application.CompanyName?

This is an assembly attribute. The VS development environment sets it in the AssemblyInfo.cs (vb) file. If
you open that file, you will see a block of assembly attributes that you can set, including company and
version numbers.

[assembly: AssemblyCompany("Syncfusion, Inc.")]

2. Windows Forms Controls FAQ Home


2.1 How do you prevent serialization of certain child controls in your Composite Control?
2.2 How do I get hold of the currently focused Control?
2.3 Why do calling Focus() on a control not set focus on it?
2.4 How do I listen to windows messages in my Control?
2.5 How do I programatically change the color of a control?
2.6 How can I change the Border color of my control?
2.7 Why should I provide a Non-Client border to my Control derived class?
2.8 How do I provide a 2 pixel 3d border in the Non-Client area of my Control derived class?
2.9 How do I provide a 1 pixel border in the NonClient area of my Control?
2.10 How do I invalidate a control including it's NonClient area?
2.11 How can I implement a scrollable picture box?
2.12 How can I put Controls, a ProgressBar for example, into a StatusBar?
2.13 How do I implement an ownerdrawn statusbar so I can put a progressbar in it?
2.14 How would I change the icon that appears on the toolbox for a custom control?
2.15 A control's Validating event is hit even when the user clicks on the Close box. How can I avoid this
behavior?
2.16 I would like to prevent validation in my textbox when the user clicks on my Cancel button, how do
I do this?
2.17 Why does adding images to an ImageList in the designer cause them to lose their alpha channel?
2.18 Why do the XP Icons when drawn using Graphics.DrawImage not draw transparently?
2.19 Why do the XP Icons that have alpha channel not draw properly when associated with controls like
ListView?
2.20 How do I prevent resizing of my Controls by the user, via Docking or anchoring or manual resizing
during design-time?
2.21 What control do I use to insert Separator lines between Controls in my Dialog?
2.22 How can I make my controls transparent so the form's background image can show through them?
2.23 How do I create an editable listbox with an in-place TextBox and Button?
2.24 How do I determine the width/height of the Non-Client area (like the border in a textbox) of a
Control?
2.25 How can I programmatically manipulate Anchor styles?
2.26 What is the best method to override in custom Controls to perform custom initialization during
runtime?
2.27 I set a Control's Visible property to true and in the immediate next statement, it returns false. Why
doesn't setting the Visible property 'take'?
2.28 I'm trying to make the background of my linklabel transparent so a picturebox will show through it.
However, if I set the link label's BackColor property to Transparent the label still has a white background.
Why?
2.29 How do I dynamically load a control from a DLL?
2.30 What is the (DynamicProperties) item listed on a control's property page in VS.NET?
2.31 How can I make a Panel or Label semi-transparent on a Windows Form?
2.32 How can I add a control to a Window Form at runtime?
2.33 How do I make the arrow keys be accepted by a control (such as a button) and not handled
automatically by the framework's focus management?
2.34 In the property browser for a custom control, how do I disable a property initially, but enable it later
based on some other property changing?
2.35 How can I have the control designer create the custom editor by calling the constructor with the
additional parameters rather than the default constructor?
2.36 How do I listen to the screen resolution change in my control?
2.37 How do I determine which button in a Toolbar is clicked?

2.1 How do you prevent serialization of certain child controls in your Composite Control?

One solution is to use a panel that has a picturebox placed on it with DockStyle.Fill. This will make the
picturebox assume the size of the panel. In addition, set the DockPadding.All property to the width of the
desired border. Then in the Panel's OnPaint method, call the baseclass and then paint the desired borders.

Here are both VB and C# projects that illustrate how you might go about this. The derived PicturePanel
class has properties that allow you to set the bordersize and color as well as the image that is to be
displayed. This sample retrieves the image from an embedded
2.2 How do I get hold of the currently focused Control?

The .Net framework libraries does not provide you an API to query for the focused Control. You have to
invoke a windows API to do so:

[C#]
public class MyForm : Form
{
[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.Winapi)]
internal static extern IntPtr GetFocus();

private Control GetFocusedControl()


{
Control focusedControl = null;
// To get hold of the focused control:
IntPtr focusedHandle = GetFocus();
if(focusedHandle != IntPtr.Zero)
// Note that if the focused Control is not a .Net control, then this will return null.
focusedControl = Control.FromHandle(focusedHandle);
return focusedControl;
}
}
[VB.Net]
Public Class Form1

' Declare the GetFocused method here:


_
Public Shared Function GetFocus() As IntPtr
End Function
Private Function GetFocusedControl() As Control
Dim focusedControl As Control = Nothing
' To get hold of the focused control:
Dim focusedHandle As IntPtr = GetFocus()
If IntPtr.Zero.Equals(focusedHandle) Then
' Note that if the focused Control is not a .Net control, then this will return null.
focusedControl = Control.FromHandle(focusedHandle)
End If
Return focusedControl
End Function
End Class

2.3 Why do calling Focus() on a control not set focus on it?

Note that when you call this method the control should be visible, otherwise the focus will not be set.
Hence calling this in say Form_Load on a control in the form will be ineffective. You should instead
consider give that control an appropriate TabIndex, so that it will be the first focused control.
2.4 How do I listen to windows messages in my Control?

In a derived class you should override WndProc as follows (listening to the WM_KEYUP message, for
example):

[C#]
public class MyCombo : ComboBox
{
private const int WM_KEYUP = 0x101;

protected override void WndProc(ref System.Windows.Forms.Message m)


{
if(m.Msg == WM_KEYUP)
{
return; //ignore the keyup
}
base.WndProc(ref m);
}
}
[VB.NET]
Public Class MyTextBox
Inherits TextBox
Private WM_KEYUP As Integer = &H101

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)


If m.Msg = WM_KEYUP Then
Return 'ignore the keyup
End If
MyBase.WndProc(m)
End Sub 'WndProc
End Class 'MyTextBox

2.5 How do I programatically change the color of a control?

Use the properties BackColor and ForeColor.

button1.BackColor = Color.White;
button1.ForeColor = Color.Blue;

2.6 How can I change the Border color of my control?

Override the OnPaint. Here is some code for a derived Button.

[C#]
public class MyButton : Button
{
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
int borderWidth = 1;
Color borderColor = Color.Blue;
ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, borderColor,
borderWidth, ButtonBorderStyle.Solid, borderColor, borderWidth,
ButtonBorderStyle.Solid, borderColor, borderWidth, ButtonBorderStyle.Solid,
borderColor, borderWidth, ButtonBorderStyle.Solid);
}
}

[VB.NET]
Public Class MyButton
Inherits Button
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
Dim borderWidth As Integer = 1
Dim borderColor As Color = Color.Blue
ControlPaint.DrawBorder(e.Graphics, e.ClipRectangle, borderColor, borderWidth,
ButtonBorderStyle.Solid, borderColor, borderWidth, ButtonBorderStyle.Solid, borderColor, borderWidth,
ButtonBorderStyle.Solid, borderColor, borderWidth, ButtonBorderStyle.Solid)
End Sub 'OnPaint
End Class 'MyButton

2.7 Why should I provide a Non-Client border to my Control derived class?

Providing a border in the non-client region of your control rather than in the ClientRectangle has very many
advantages:

When you include a scrollbar in your control, the scrollboar will appear inside the border, rather than
to the outside if you drew the border in the client area.
When you allow custom painting of the control, your user will not draw over the NC border.
Your own client painting code will be simplified in that you will not have to bother about taking the
border into account while painting the client area. The next faq will tell you how to include a non-client
border.

2.8 How do I provide a 2 pixel 3d border in the Non-Client area of my Control derived class?

You can do so as follows by overriding the CreateParams property in your Control. The advantage with this
approach is that drawing is handled by the system as soon as you set the flag below.

protected override CreateParams CreateParams


{
get
{
CreateParams cparams;

cparams = base.CreateParams;
if(this.need3DBorder)
{
cparams.ExStyle &= ~512;
cparams.Style &= ~8388608 /*WS_BORDER*/;
cparams.ExStyle = cparams.ExStyle | 512 /*WS_EX_DLGFRAME*/;
}
return cparams;
}
}

2.9 How do I provide a 1 pixel border in the NonClient area of my Control?

You will have to first provide some space in the NC area by setting the WS_BORDER flag in
CreateParams and then draw the border yourself by listening to the WM_NCPAINT message in your
Control, as follows:

protected override CreateParams CreateParams


{
get
{
System.Windows.Forms.CreateParams cp = base.CreateParams;
if(this.needFlatBorder)
{
cparams.ExStyle &= ~512 /*WS_EX_CLIENTEDGE*/;
cparams.Style &= ~8388608 /*WS_BORDER*/;
cp.Style |= 0x800000; // WS_BORDER
}
}
}
protected override void WndProc(ref Message m)
{
if(m.Msg == 133/*WM_NCPAINT*/)
{
this.DrawFlatNCBorder(ref m);
}
base.WndProc(ref m);
}
private void DrawFlatNCBorder(ref Message msg)
{
IntPtr hRgn1 = (IntPtr) msg.WParam;
// The update region is clipped to the window frame. When wParam is 1, the entire window frame
needs to be updated.

IntPtr hdc = NativeMethods.GetDCEx(msg.HWnd, hRgn1, 1/*DCX_WINDOW*/|


0x0020/*DCX_PARENTCLIP*/);
if (hdc != IntPtr.Zero)
{
using (Graphics g = Graphics.FromHdc(hdc))
{
Rectangle bounds = new Rectangle(0,0,this.Width,this.Height);

ControlPaint.DrawBorder(g,bounds,this.borderColor,ButtonBorderStyle.Solid);

// create a clipping region for remaining parts to be drawn excluding


// the border we did just drew
bounds.Inflate(-1, -1);
IntPtr hRgn2 = NativeMethods.CreateRectRgn(bounds.Left, bounds.Top, bounds.Right, bounds.Bottom);
if(hRgn2 == (IntPtr)1)
{
// Provide a new clipping region.
msg.WParam = (IntPtr) hRgn2;
}
else
{
// combine with existing clipping region.
NativeMethods.CombineRgn(hRgn1, hRgn1, hRgn2, NativeMethods.RGN_AND);
NativeMethods.DeleteObject(hRgn2);
}
}

msg.Result = (IntPtr) 1;
NativeMethods.ReleaseDC(msg.HWnd, hdc);
}
Invalidate();
}

2.10 How do I invalidate a control including it's NonClient area?

You can do so as follows in your Control:

private void InvalidateWindow()


{
NativeMethods.RedrawWindow(this.Handle, IntPtr.Zero, IntPtr.Zero,
0x0400/*RDW_FRAME*/ | 0x0100/*RDW_UPDATENOW*/
| 0x0001/*RDW_INVALIDATE*/);
}

2.11 How can I implement a scrollable picture box?

See Mike Gold's article on C# Corner for a detailed discussion.

2.12 How can I put Controls, a ProgressBar for example, into a StatusBar?
You cannot place controls into a StatusBar control in the designer. However, you can add any no. of
Controls to the StatusBar programatically through it's Controls property. After adding the Controls, set their
Visible, Location and Bounds property appropriately.

You could then create a status bar that looks like this, for example:

2.13 How do I implement an ownerdrawn statusbar so I can put a progressbar in it?

Check out the code posted originally in VB by Jacob Grass, and translated to C# by Jason Lavigne on the
dotnet.discussion newsgroup at develop.com.

2.14 How would I change the icon that appears on the toolbox for a custom control?

You can do this in different ways explained below. In all the cases the bitmap or icon should follow these
rules:

• The bitmap or icon dimension should be 16X16 with 16 colors.


• The left-bottom pixel-color will be assumed to be the transparent color.

Technique 1: Use a bitmap (not an icon, in the embedded resource) file implicitly without specifying the
ToolboxBitmapAttribute for the type:

Say, you have a custom control MyControl in the namespace MyNamespace, create a bmp file
MyControl.bmp following the above rules. Add this file to your project at the top-level and make it an
embedded resource. The project's default namespace should be MyNamespace.

If the control's namespace and the project's default namespace don't match then move the bitmap to
appropriate subfolders so that they match. If this is not possible, typically when the namespaces are not
related at all then you cannot use this technique, use instead one of the techniques below using the
ToolboxBitmap attribute.

Create the assembly and the next time you add it to the toolbox the custom image in MyControl.bmp
should be available in the toolbox.

This is the easiest technique to implement as it doesn't require you to use the ToolboxBitmapAttribute in
your type defenition.

Technique 2: Use ToolboxBitmap attribute.

Example 1:

Use a bitmap (not icon) in the embedded resource with the same name as the type.

Default Assembly Namespace: "MyAssemblyNamespace"

namespace MyAssemblyNamespace
{
[ToolboxBitmap(typeof(MyCustomType))]
public class MyCustomType : Component
{...}
}

In the above scenario the runtime will look for a embedded bmp file of name MyCustomType.bmp in the
project's root directory. Note that the default namespace and the type's namespace match.

Example 2:

If you want your icons in sub-directories then change the attribute like this:
[ToolboxAttribute(typeof(MyCustomType), "ToolboxIcons.MyCustomType.bmp")]

or

[ToolboxAttribute(typeof(MyCustomType), "ToolboxIcons.MyCustomType.ico")]

where the bmp or ico file (yap, now, when you explicity specify the resource, you can use an ico file) is in a
sub-directory called "ToolboxIcons".

Example 3:

Sometimes your type's namespace and the default assembly namespace may be unrelated, in which case
you have to use a different type that has the same namespace as the default assembly namespace to scope
the embedded image file.

Default namespace: "MyAssemblyNamespace"

namespace MyAssemblyNamespace
{
public class SomeType
{...}
}
namespace DifferentNamespace
{
// Using SomeType which has the same namespace as the default assembly namespace to scope the
embedded resource.
[ToolboxBitmap(typeof(SomeType), "MyCustomType.ico")]
public class MyCustomType
{...}
}

In this case the runtime will look for the above resource at the top-most directory. If your icons were in a
subdirectory named "ToolboxIcons" then the attribute would look like this:

[ToolboxBitmap(typeof(SomeType), "ToolboxIcons.MyCustomType.ico")]
2.15 A control's Validating event is hit even when the user clicks on the Close box. How can I avoid this
behavior?

One way is to add code to your Validating handler and only execute the validation routine if the mouse is in
the client area. This will avoid the click on the title bar and its system menu. You might also want to add
special handling for the tab key so your validation is hit independent of the mouse location when you tab
off the control.

private bool tabKeyPressed = false;

private void textBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e)


{
if(tabKeyPressed ||
this.ClientRectangle.Contains(this.PointToClient(Cursor.Position)))
{
if(boolNotOKValues) //do your validating
e.Cancel = true; //failed
}
tabKeyPressed = false;
}

protected override bool ProcessDialogKey(Keys keyData)


{
tabKeyPressed = keyData == Keys.Tab;
return base.ProcessDialogKey(keyData);
}

2.16 I would like to prevent validation in my textbox when the user clicks on my Cancel button, how do I
do this?

Say textBox1 and canelButton and the control names, then this is how you could do this:

[C#]
// Handler to the Validating event of the TextBox.
private void TextBox_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
if (!this.cancelButton.Focused)
{
// Do this only when the cancel button is not clicked.
if(invalidState)
e.Cancel = true;
}
}
[VB.Net]
' Handler to the Validating event of the TextBox.
Private Sub TextBox_Validating(ByVal sender As Object, ByVal e As
System.ComponentModel.CancelEventArgs)
If Not Me.cancelButton.Focused Then
' Do this only when the cancel button is not clicked.
If invalidState Then
e.Cancel = True
End If
End If
End Sub

2.17 Why does adding images to an ImageList in the designer cause them to lose their alpha channel?

Looks like the ImageList editor loses the transparency when it does some internal copy/clone of the images.
However, it seems that it does work when you add the images in code to the ImageList.

One workaround (not so tidy) is to add the images to the ImageList in the design time (so that your design-
time will be closer to the runtime) and then clear that ImageList and refill it with the images again, in code.

Take a look at this faq on how to add images to your project and retrive them programatically during
runtime. Adding image files to a project as an embedded resource and retrieving them programatically.

2.18 Why do the XP Icons when drawn using Graphics.DrawImage not draw transparently?

Note that it's only the ImageList class that can draw an Icon with alpha channel properly. So, instead of
using the Graphics.DrawImage method, first associate this icon to a ImageList and then use the
ImageList.Draw method to draw the icon. Also, note that this is possible only in XP with XP Themes
enabled for that application.

2.19 Why do the XP Icons that have alpha channel not draw properly when associated with controls like
ListView?

Make sure that you include the manifest file that will enable XP themes support for you application. Then
the icons with alpha channel will draw semi-transparently.

2.20 How do I prevent resizing of my Controls by the user, via Docking or anchoring or manual resizing
during design-time?

The best place to ensure a particular height/width for you control is in the SetBoundsCore override of your
Control, as follows:
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
{
int prefHeight = this.GetPreferredHeight();
// Ensure that the height is atleast as big as prefHeight
if(height < prefHeight)
height = prefHeight;

base.SetBoundsCore(x, y, width, height, specified);


}
Protected Overrides Sub SetBoundsCore(ByVal x As Integer, ByVal y As Integer, ByVal width As
Integer, ByVal height As Integer, ByVal specified As BoundsSpecified)
Dim prefHeight As Integer = Me.GetPreferredHeight()
' Ensure that the height is atleast as big as prefHeight
If height < prefHeight Then
height = prefHeight
End If

MyBase.SetBoundsCore(x, y, width, height, specified)


End Sub

2.21 What control do I use to insert Separator lines between Controls in my Dialog?

Use the Label Control with the BorderStyle set to Fixed3D and height set to 2.

2.22 How can I make my controls transparent so the form's background image can show through them?

By default, a control's background color will be the same as the container's background. In the picture
below, the form's background was set to Color.Red. In design mode, you can see the four controls have the
red background, but since the form's Image was set to a bitmap, you cannot see the form's red background.
To make the controls' background transparent, you can set the alpha blend value of their background to
zero. In code, you could use:

public Form1()
{
InitializeComponent();

checkBox1.BackColor = Color.FromArgb(0, checkBox1.BackColor);


button1.BackColor = Color.FromArgb(0, button1.BackColor);
linkLabel1.BackColor = Color.FromArgb(0, linkLabel1.BackColor);
label1.BackColor = Color.FromArgb(0, label1.BackColor);
// Or use the System.Drawing.Color.Transparent color.
}

In design mode, you can set the alpha blend value to zero by typing the four component in the property
grid. So, for each control's BackColor property, you would type 0,255,0,0 to make it a tranparent red.

Here is a VB project using this idea.


2.23 How do I create an editable listbox with an in-place TextBox and Button?

The attached EditableList UserControl implements an editable listbox with an in-place TextBox and Button
allowing users to directly edit the contents of the list box.

When the user clicks on a selected item, a textbox and a button is shown over the selected item and the user
can directly edit the selectected item text. The button can be programmed to show for example a
OpenFileDialog to allow user to select a file (useful while implementing a Files list).

2.24 How do I determine the width/height of the Non-Client area (like the border in a textbox) of a
Control?

One generic way for all Controls is to get the difference between the ClientRectangle's width and the
Control.Bounds' width. That should give the border width (and in general the NC area width); similarly for
height.

2.25 How can I programmatically manipulate Anchor styles?

You can do this using the bitwise operators &, | and ^ ( And, Or and Xor (or &, Or, ^) in VB.Net). Here is
code that will toggle label1 being anchored on the left.

[C#]
private void button1_Click(object sender, System.EventArgs e)
{
if ((label1.Anchor & AnchorStyles.Left) == 0)
{ //add it
label1.Anchor = label1.Anchor | AnchorStyles.Left;
}
else if ((label1.Anchor & AnchorStyles.Left) != 0)
{ //remove
label1.Anchor = label1.Anchor ^ AnchorStyles.Left;
}
}
[VB.NET]
Private Sub button1_Click(sender As Object, e As System.EventArgs)
If(label1.Anchor And AnchorStyles.Left) = 0 Then
'add it
label1.Anchor = label1.Anchor Or AnchorStyles.Left
ElseIf(label1.Anchor And AnchorStyles.Left) <> 0 Then
'remove
label1.Anchor = label1.Anchor Xor AnchorStyles.Left
End If
End Sub 'button1_Click
2.26 What is the best method to override in custom Controls to perform custom initialization during
runtime?

When custom initialization is to be done during runtime on certain Controls, the best way is to implement
the ISupportInitialize interface in that Control. Then the BeginInit method will be called as soon as the
Control gets created and EndInit will be called after the design-time initialization of that control.

2.27 I set a Control's Visible property to true and in the immediate next statement, it returns false. Why
doesn't setting the Visible property 'take'?

A control's Visible property will also depend on it's parent control's (if any) visible property. If the parent
control is not visible, the control will also return false.

2.28 I'm trying to make the background of my linklabel transparent so a picturebox will show through it.
However, if I set the link label's BackColor property to Transparent the label still has a white background.
Why?

Controls with a "Transparent" color actually render their parent's background, so you're seeing the White
background of the Form, not the PictureBox. Three easy ways to deal with this:

• Use a Panel with it's "BackgroundImage" property set instead of a PictureBox, and parent the
LinkLabels to the panel (PictureBoxes generally don't have children)
• Set the BackgroundImage of the Form to the image (basically the same as 1 above, but avoids the
extra control)
• In code, set the Parent of the LinkLabel to be the PictureBox. You'll need to update the LinkLabel's
position to match the new origin of the parent if the PictureBox isn't at (0,0)

(Shawn Burke on microsoft.public.dotnet.framework.windowsforms newsgroup)

2.29 How do I dynamically load a control from a DLL?

You use System Reflection to dynamically load a control. If the DLL is named "SpecControls.DLL" and
the class you want is "SpecControls.ColorControl", then use this code.

[C#]
// load the assembly
System.Reflection.Assembly assembly = Assembly.LoadFrom("SpecControls.DLL");

// get the type


Type t = assembly.GetType("MyControls.MyControl");

// create an instance and add it.


//
Control c = (Control)Activator.CreateInstance(t);
parent.Controls.Add(c);

[VB.NET]
' load the assembly
Dim assembly1 As System.Reflection.Assembly = Assembly.LoadFrom("SpecControls.DLL")

' get the type


Dim t As Type = assembly1.GetType("MyControls.MyControl")

' create an instance and add it.


'
Dim c As Control = CType(Activator.CreateInstance(t), Control)
parent.Controls.Add(c)

2.30 What is the (DynamicProperties) item listed on a control's property page in VS.NET?

Clicking Advanced... under this DynamicProperties option in the control properties displays certain control
properties that can be set through an XML app.config file that is added to your project. This file stores the
dynamic property values and is automatically read during the intialization process on the form at design
time. You can manually edit this file to change the properties and next when you run the application,
controls will pick up the new values. This file is used strictly for design time initializations.

2.31 How can I make a Panel or Label semi-transparent on a Windows Form?

You can make a panel or label transparent by specifying the alpha value for the Background color.

panel.BackColor = Color.FromArgb(65, 204, 212, 230);

In the designer you have to enter these values manually in the edit box. Don't select the color using the
ColorPicker.

2.32 How can I add a control to a Window Form at runtime?

To add a control at runtime, you do three steps:

• 1. Create the control


• 2. Set control properties
• 3. Add the control to the Form's Controls collection

In general, if you need help on exactly what code you need to add, just look at the code generated by the
designer when you add the control at design time. You can generally use the same code at runtime.
Here are code snippets that create a textBox at runtime.
[C#]
//step 1
TextBox tb = new TextBox();

//step2
tb.Location = new Point( 10, 10);
tb.Size = new Size(100, 20);
tb.Text = "I was created at runtime";

//step3
this.Controls.Add(tb);

[VB.NET]

'step 1
Dim tb as TextBox = New TextBox()

'step2
tb.Location = New Point( 10, 10)
tb.Size = New Size(100, 20)
tb.Text = "I was created at runtime"

'step3
Me.Controls.Add(tb)

2.33 How do I make the arrow keys be accepted by a control (such as a button) and not handled
automatically by the framework's focus management?

By default, the arrow keys are not handled by a control's key processing code, but instead are filtered out
for focus management. Hence, the control's KeyDown, KeyUp and KeyPressed events are not hit when you
press an arrow. If you want your control to handle these keyboard events, you tell the framework by
overriding your control's IsInputKey method.

protected override bool IsInputKey(Keys key)


{
switch(key)
{
case Keys.Up:
case Keys.Down:
case Keys.Right:
case Keys.Left:
return true;
}
return base.IsInputKey(key);
}
2.34 In the property browser for a custom control, how do I disable a property initially, but enable it later
based on some other property changing?

Implement ICustomTypeDescriptor, and provide your own PropertyDescriptor for that property that
changes it's return value for IsReadOnly.

2.35 How can I have the control designer create the custom editor by calling the constructor with the
additional parameters rather than the default constructor?

You can do this by creating the editor yourself rather than allowing TypeDescriptor to do it:

1) Shadow the property you care about in your designer...

protected override void PreFilterProperties(IDictionaryProperties props)


{
PropertyDescriptor basePD = props["MyProperty"];
props["MyProperty"] = new EditorPropertyDescriptor(basePD);
}

2) Create a property descriptor that "wraps" the original descriptor

private class EditorPropertyDescriptor : PropertyDescriptor


{
private PropertyDescriptor basePD;
public EditorPropertyDescriptor(PropertyDescriptor base)
{
this.basePD = base;
}

// now, for each property and method, just delegate to the base...
public override TypeConverter Converter
{
get { return basePD.Converter; }
}

public override bool CanResetValue(object comp)


{
return basePD.CanResetValue(comp);
}

// and finally, implement GetEditor to create your special one...

3) create your editor by hand when it's asked for


public override object GetEditor(Type editorBaseType)
{
if (editorBaseType == typeof(UITypeEditor))
{
return new MyEditor(Param1, param2, param3);
}
return basePD.GetEditor(editorBaseType);
}
}

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

2.36 How do I listen to the screen resolution change in my control?

You should override WndProc in your control/form and listen to the WM_DISPLAYCHANGE message.
Refer to this faq a WndProc override sample:

How do I listen to windows messages in my Control?

http://www.syncfusion.com/faq/winforms/search/1064.asp

2.37 How do I determine which button in a Toolbar is clicked?

When you click on a button on a Toolbar the click is sent to the Toolbar, so you need to check the
ToolBarButtonClickEventArgs's button property to determine the button on the Toolbar that was clicked.

[C#]
private void toolBar1_ButtonClick(object sender, System.Windows.Forms.ToolBarButtonClickEventArgs
e)
{
//check if toolBarButton1 was clicked
if (e.Button == toolBarButton1)
{
MessageBox.Show("Button 1 clicked");
}
}

[VB.NET]
Private Sub toolBar1_ButtonClick(ByVal sender As Object, ByVal e As
System.Windows.Forms.ToolBarButtonClickEventArgs)
'check if toolBarButton1 was clicked
If e.Button = toolBarButton1 Then
MessageBox.Show("Button 1 clicked")
End If
End Sub
© 2001-06 Copyright George Shepherd.

3. Windows Forms Books FAQ Home


3.1 Windows Forms Programming in C#?
3.2 Programming Microsoft Windows with C#?
3.3 C# Design Patterns?

3.1 Windows Forms Programming in C#?

Windows Forms Programming in C# by Chris Sells ISBN: 0321116208

An excellent book for learning Windows Forms using C# for both Beginners and experienced Progammers.
The presentation is nice and crisp the chapter size is usually around 50 pages, presenting all the necessary
details and at the same time maintaining the reader's interest in the topic being presented.

3.2 Programming Microsoft Windows with C#?

Programming Windows(r) with C# (Core Reference)


by Charles Petzold

ISBN: 0735613702

This is an excellent book for both Windows Forms and GDI+. As the title suggests it is oriented towards C#
programmers. VB programmers should have no trouble following along. Petzold writes lucid prose.
Update: There is a VB.NET version of this book available now. Programming Microsoft Windows with
Microsoft Visual Basic .NET (Core Reference). ISBN: 0735617996.

3.3 C# Design Patterns?

C# Design patterns by James W. Cooper. ISBN: 0201844532

This is a good book to learn about patterns through a C#/Windows Forms lens. Several of the samples are
UI related and use Windows Forms.

4. Windows Forms Data Binding

FAQ Home
4.1
Does MySql work with ADO.NET?
4.2
Where can I find a discussion of databinding and windows forms?
4.3
How do I test for a null value in DataView.RowFilter?
4.4
I don't have SQL Server. Is there any way to run the samples that need SQL server?
4.5
How can I programmatically move through a dataset that has bound controls?
4.6
When I try to update a dataset I get an error that the system is unable to find "Table"?
4.7
How can I bind an ArrayList to a DataGrid?
4.8
When I try to bind two comboboxes to the same datatable, both boxes show the same values, changing one
changes the other. How do I make them have distinct values?
4.9
How do I bind a mdb file to a datagrid?
4.10
How do I bind a listbox or a combobox to a MDB file?
4.11
In my databound ComboBox, how do I set the SelectedItem property?
4.12
Are server side cursors supported in .NET?
4.13
I am populating a ListBox by binding it to an ArrayList. The initial display is OK, but later changes to my
ArrayList are not shown in my ListBox. How can I get the changes to show properly?
4.14
My SQL server runs on a non-default port. How can I specify this port in my connection string?
4.15
What is a DataSet?
4.16
How do I add updating support to a dataset?
4.17
How can I import a CSV file into a DataTable?
4.18
How can I prevent a ComboBox and DataGrid bound to the same DataTable from sharing the same current
position?
4.19
I get a 'This would cause two bindings in the collection to bind to the same property' error message. What
might cause this?
4.20
How do I bind a TextBox to a nested relation?
4.21
How do I call a SQL stored procedure?
4.22
I programatically change a bound TextBox value, but the value does not get pushed back into the bound
datasource. How can I make sure the DataSource is updated?
4.23
Why does the CheckedListBox lose checked state when placed in a tab page that gets hidded and shown?

4.1 Does MySql work with ADO.NET?

MYSQL can be used with ADO.NET. There is more information available here:
http://www.mysql.com/articles/dotnet/

4.2 Where can I find a discussion of databinding and windows forms?

Take a look at the Microsoft KB article, INFO: Roadmap for Windows Forms Data Binding (Q313482).
This article gets you started. It also lists other Microsoft KB articles that have to do with using the
Windows Forms DataGrid and databinding.

4.3 How do I test for a null value in DataView.RowFilter?

You can use the IsNull operator.

[C#]
//the outer quotes are double quotes and the inner quotes are 2 single quotes
//Fax is the column mapping name
this.dataView1.RowFilter = "IsNull(Fax, '') = ''";

// for a numeric null in custNo (suggested by Bob Gibson)


this.dataView1.RowFilter = "IsNull(custNo, 0) = 0";

[VB.NET]
'the outer quotes are double quotes and the inner quotes are 2 single quotes
'Fax is the column mapping name
Me.dataView1.RowFilter = "IsNull(Fax, '') = ''"

' for a numeric null in custNo (suggested by Bob Gibson)


Me.DataView1.RowFilter = "IsNull(custNo, 0) = 0"

4.4 I don't have SQL Server. Is there any way to run the samples that need SQL server?

You can use MSDE, a SQL server compatible database engine that MS makes available for free. You can
download and install MSDE from a whole variety of sources. Here is one source.

MSDE also comes with Visual Studio.NET / .NET framework SDK. It is available under $(VS Install
drive):\Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Samples\Setup\msde. You can then
run $(VS Install drive):\Program Files\Microsoft Visual Studio
.NET\FrameworkSDK\Samples\Setup\configsamples.exe to configure the northwind database that the
samples use.

4.5 How can I programmatically move through a dataset that has bound controls?

You have to access a property called the Binding Context and then retrieve the BindingContext associated
with the dataset and data member that you used for binding. After you have access to this object you just set
the position property. You can move backward and forward through the dataset.

Download a working sample that shows this: simpledata5.zip

form.BindingContext[this.dataSet, "Customers"].Position -= 1;

Remember that when you scroll through the dataset all associated controls will scroll since they all depend
on the same context. This is useful if you want to have several controls that display sections of a row
operate in tandem.

4.6 When I try to update a dataset I get an error that the system is unable to find "Table"?
Are you calling Update on the dataset like this without specifying the name of the table that you are
updating. The problem is that when table names are not given the system assumes a table name of 'Table'.
This of course causes the update to fail.

this.dataAdapter.Update(this.dataSet);

If so just change this line to

this.dataAdapter.Update(this.dataSet, "Customers");
// replace 'Customers' with the table that you have

4.7 How can I bind an ArrayList to a DataGrid?

Here is a technique for binding an arraylist of objects where the objects contain public property that can
appear as columns in the datagrid. In this example, the object contains 2 public doubles, one named value
and the other named sqrt. To bind this arraylist to a datagrid, add a custom tablestyle that has a
MappingName of "ArrayList", and then use the property names as the MappingName for each column.
Below are some code snippets. You can download a working project that also has code to delete rows and
add new rows to the bound arraylist.

private void Form1_Load(object sender, System.EventArgs e)


{
CreateArrayList();
BindArrayListToGrid();
}

private void BindArrayListToGrid()


{
dataGrid1.DataSource = arrayList1;

//create a custom tablestyle and add two columnstyles


DataGridTableStyle ts = new DataGridTableStyle();
ts.MappingName = "ArrayList";

int colwidth = (dataGrid1.ClientSize.Width - ts.RowHeaderWidth -


SystemInformation.VerticalScrollBarWidth - 5) / 2;

//create a column for the value property


DataGridTextBoxColumn cs = new DataGridTextBoxColumn();
cs.MappingName = "value"; //public property name
cs.HeaderText = "Random Number";
cs.Format = "f4";
cs.Width = colwidth;
ts.GridColumnStyles.Add(cs);
//create a column for the sqrt property
cs = new DataGridTextBoxColumn();
cs.MappingName = "sqrt"; //public property name
cs.HeaderText = "Square Root";
cs.Format = "f4";
cs.Width = colwidth;
ts.GridColumnStyles.Add(cs);

dataGrid1.TableStyles.Clear();
dataGrid1.TableStyles.Add(ts);
}

private void CreateArrayList()


{
arrayList1 = new ArrayList();

//add some items


Random r = new Random();
for (int i = 0; i < 20; ++i)
arrayList1.Add(new RandomNumber(r.NextDouble()));

//create a struct or class that defines what you want in each row
//the different columns in the row must be public properties
public struct RandomNumber
{
private double number;

public RandomNumber(double d)
{
number = d;
}

public double value


{
get{ return number; }
set{ number = value;}
}

public double sqrt


{
get {return Math.Sqrt(this.value);}
}
}
4.8 When I try to bind two comboboxes to the same datatable, both boxes show the same values,
changing one changes the other. How do I make them have distinct values?

Make sure the two comboboxes use different BindngContext objects.

BindingContext bc = new BindingContext();


this.comboBox1.BindingContext = bc;
comboBox1.DataSource = _dataSet.Tables["orders"];
comboBox1.ValueMember = "CustomerID";
comboBox1.DisplayMember = "CustomerID";

bc = new BindingContext();
this.comboBox2.BindingContext = bc;
comboBox2.DataSource = _dataSet.Tables["orders"];
comboBox2.ValueMember = "CustomerID";
comboBox2.DisplayMember = "CustomerID";

4.9 How do I bind a mdb file to a datagrid?

You can use the classes in the System.Data.OleDb namespace to read a MDB file into a datagrid. You
instantiate a OleDbConnection object using a connection string to your MDB file. You then instantiate a
OleDbDataAdapter that uses this connection object and a SQL query. Next you create a DataSet object, use
the OleDbDataAdapter to fill this dataset, and finally attached this dataset to your datagrid. Here is the code
that does this.

private void Form1_Load(object sender, System.EventArgs e)


{
// Set the connection and sql strings
// assumes your mdb file is in your root
string connString = @"Provider=Microsoft.JET.OLEDB.4.0;data source=C:\northwind.mdb";
string sqlString = "SELECT * FROM customers";

// Connection object
OleDbConnection connection = new OleDbConnection(connString);

// Create data adapter object


OleDbDataAdapter dataAdapter = new OleDbDataAdapter(sqlString, connection);

// Create a dataset object and fill with data using data adapter's Fill method
DataSet dataSet = new DataSet();
dataAdapter.Fill(dataSet, "customers");

// Attach dataset's DefaultView to the datagrid control


dataGrid1.DataSource = dataSet.Tables["customers"].DefaultView;
}

4.10 How do I bind a listbox or a combobox to a MDB file?

You can use the classes in the System.Data.OleDb namespace to read a MDB file into a ListBox and a
ComboBox. You instantiate a OleDbConnection object using a connection string to your MDB file. You
then instantiate a OleDbDataAdapter that uses this connection object and a SQL query. Next you create a
DataSet object, use the OleDbDataAdapter to fill this dataset, and finally attached this dataset to your
control. Here is the code that does this.

private void Form1_Load(object sender, System.EventArgs e)


{
// Set the connection and sql strings
// assumes your mdb file is in your root
string connString = @"Provider=Microsoft.JET.OLEDB.4.0;data source=C:\northwind.mdb";
string sqlString = "SELECT * FROM customers";

// Connection object
OleDbConnection connection = new OleDbConnection(connString);

// Create data adapter object


OleDbDataAdapter dataAdapter = new OleDbDataAdapter(sqlString, connection);

// Create a dataset object and fill with data using data adapter's Fill method
DataSet dataSet = new DataSet();
dataAdapter.Fill(dataSet, "customers");

// Attach dataset's DefaultView to the combobox


listBox1.DataSource = dataSet.Tables["customers"].DefaultView;
listBox1.DisplayMember = "CustomerID";

// Attach dataset's DefaultView to the combobox


comboBox1.DataSource = dataSet.Tables["customers"].DefaultView;
comboBox1.DisplayMember = "CustomerID";
}

Notice that this code uses the same dataset object for both the listbox and the combobox. When done in this
manner, the two controls are linked so that the selection in one control will be the selection in the other
control. If you edit an entry in the combobox, the same entry is the listbox is changed. To avoid this
linkage, just have a second dataset object for your second control.
4.11 In my databound ComboBox, how do I set the SelectedItem property?

Use the FindStringExact method. For example, if you have set the ComboBox's ValueMember property to
"OrderID", then you could call

comboBox1.SelectedIndex = comboBox1.FindStringExact(stringOrderID);

where stringOrderID is the "orderID" of the row to be selected.

4.12 Are server side cursors supported in .NET?

No. Nicholas Paldino gives the following response in a position to the


microsoft.public.dotnet.framework.odbcnet newsgroup.

There are no updateable cursors ANYWHERE in .NET for that matter. The way .NET handles data is you
push it into a dataset. The dataset keeps track of the changes that are made, and then you pass the data set
back to a data adapter, which will fire off the appropriate insert, update, and delete statements in order to
update the underlying data source.

All of the data access in .NET is based on a disconnected data model.

4.13 I am populating a ListBox by binding it to an ArrayList. The initial display is OK, but later
changes to my ArrayList are not shown in my ListBox. How can I get the changes to show properly?

In an ArrayList, the 'plumbing' is not available to support two-way binding as with a dataset. So, you have
to handle the synchronization yourself. One way to do this is to set the listBox1.DataSource to null and
then reset it to your ArrayList. Another way is to use the CurrencyManager as shown in the code below.

private System.Windows.Forms.ListBox listBox1;


private System.Windows.Forms.Button button1;
private ArrayList myArrayList;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

myArrayList = new ArrayList();

myArrayList.Add("orange");
myArrayList.Add("green");
myArrayList.Add("blue");
myArrayList.Add("red");

listBox1.DataSource = myArrayList;
}
......
//change the arraylist
private void button1_Click(object sender, System.EventArgs e)
{
myArrayList[1] = "pink";
myArrayList.Add("lavendar");

//use currency manger to sync up the listbox


BindingManagerBase bm = this.listBox1.BindingContext[myArrayList];
CurrencyManager cm = (CurrencyManager) bm;
if (cm != null)
cm.Refresh();

//Or, you can just reset the datasource


//listBox1.DataSource = null;
//listBox1.DataSource = myArrayList;
}

4.14 My SQL server runs on a non-default port. How can I specify this port in my connection string?

The data source component of your connection string should contain the port right after the IP address (or
name). It should be separated from the IP by a comma.

data source=192.168.123.1, port number;

Take a look at this web site for great information on several connection strings.

http://www.connectionstrings.com/

4.15 What is a DataSet?

Think of a DataSet object as a local in memory copy of database tables. With the client server model, client
applications held onto a connection and updated and added records at will. With ADO.NET the dataset
presents a disconnected model. Data as well as data changes are contained in the dataset with no physical
connection to the datasource.
Changes can be reconciled against any datasource at any time.

A Dataset is not limited to database tables. It can work with XML or for that matter any other data.

4.16 How do I add updating support to a dataset?

To be able to write changes back to the datasource, the data adapter object that populates your dataset
should have commands set for updating, deleting etc. Fortunately, there is a class called
SqlCommandBuilder that generates these commands from our Select command. All we have to do is
instantiate this class passing it in the data adapter that we use.

Enclosed is a complete sample: simpledata4.zip

// Command builder will generate the command required to update the


// datasource from your select statement
SqlCommandBuilder commandBuilder = new SqlCommandBuilder(this.dataAdapter);

After this is done whenever you wish to write changes back to the data source simply call Update on the
data adapter as shown below.

if(this.dataSet != null && this.dataSet.HasChanges())


this.dataAdapter.Update(this.dataSet, "Customers");

4.17 How can I import a CSV file into a DataTable?

Here is a solution suggested by Elan Zhou (MS) on the microsoft.public.dotnet.languages.vb newsgroup.

You can also use the following code:


1. Put a DataGrid on the form.
2. Try the following sample code: (Suppose the csv is c:\test.csv.)

Imports System.Data
Imports System.Data.OleDb

Public Class Form1


Inherits System.Windows.Forms.Form
Dim objDataset1 As DataSet()

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


MyBase.Load
Dim sConnectionString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\;Extended
Properties=Text;"
Dim objConn As New OleDbConnection(sConnectionString)
objConn.Open()

Dim objCmdSelect As New OleDbCommand("SELECT * FROM test.csv", objConn)


Dim objAdapter1 As New OleDbDataAdapter()
objAdapter1.SelectCommand = objCmdSelect

Dim objDataset1 As New DataSet()


objAdapter1.Fill(objDataset1, "Test")
DataGrid1.DataSource = objDataset1.Tables(0).DefaultView
objConn.Close()
End Sub
End Class

4.18 How can I prevent a ComboBox and DataGrid bound to the same DataTable from sharing the
same current position?

If you have two controls bound to the same datasource, and you do not want them to share the same
position, then you must make sure that the BindingContext member of one control differs from the
BindingContext member of the other control. If they have the same BindingContext, they will share the
same position in the datasource.

If you add a ComboBox and a DataGrid to a form, the default behavior is for the BindingContext member
of each of the two controls to be set to the Form's BindingContext. Thus, the default behavior is for the
DataGrid and ComboBox to share the same BindingContext, and hence the selection in the ComboBox is
synchronized with the current row of the DataGrid. If you do not want this behavior, you should create a
new BindingContext member for at least one of the controls.

[C#]
private void Form1_Load(object sender, System.EventArgs e)
{
this.myDataTable = GetATable(); //get a datatable somehow...

this.dataGrid1.DataSource = myDataTable;

//set a new binding context for the combobox


this.comboBox1.BindingContext = new BindingContext();
this.comboBox1.DataSource = myDataTable;
this.comboBox1.DisplayMember = "Col1";
this.comboBox1.ValueMember = "Col1";
}

[VB.NET]
Private Sub Form1_Load(ByVal sender as Object, ByVal e as System.EventArgs)

Me.myDataTable = GetATable() 'get a datatable somehow...


Me.dataGrid1.DataSource = myDataTable

'set a new binding context for the combobox


Me.comboBox1.BindingContext = New BindingContext()
Me.comboBox1.DataSource = myDataTable
Me.comboBox1.DisplayMember = "Col1"
Me.comboBox1.ValueMember = "Col1"
End Sub

4.19 I get a 'This would cause two bindings in the collection to bind to the same property' error
message. What might cause this?

As the message suggests, the code is calling Control.DataBindings.Add twice with what amounts to the
same parameters.

One way this might happen is if you call the same code more than once in your program to reload your
datasource for some reason, and in this code, you have lines such as:

Me.TextBox1.DataBindings.Add("Text", myDataTable, "Col1Name")


Me.TextBox2.DataBindings.Add("Text", myDataTable, "Col2Name")
Me.TextBox3.DataBindings.Add("Text", myDataTable, "Col3Name")

On the second call, this would attempt to add a duplicate binding to the DataBindings collection. One
solution is to Clear the DataBindings collection before you add your new binding.

Me.TextBox1.DataBindings.Clear();
Me.TextBox1.DataBindings.Add("Text", myDataTable, "Col1Name")
Me.TextBox2.DataBindings.Clear();
Me.TextBox2.DataBindings.Add("Text", myDataTable, "Col2Name")
Me.TextBox3.DataBindings.Clear();
Me.TextBox3.DataBindings.Add("Text", myDataTable, "Col3Name")

4.20 How do I bind a TextBox to a nested relation?

Say you have a Parent table related to a Child table related to a GrandChildTable, and you want to bind a
TextBox to a column in the GrandChild table.

To do this you have to have nested relations defined, and you use this nesting to create the DataMember
parameter for the the DataBinding that you add to the TextBox. Below are some code snippets. They show
the DataMember as "ParentToChild.ChildToGrandChild.Name" which creates a path from the parent table
down to the field in the nested relation by stringing the relation names together separated with a period.
You can also download both C# and VB projects.

Dim dSet As New DataSet()

'get the tables


Dim parentTable As DataTable = GetParentTable()
Dim childTable As DataTable = GetChildTable()
Dim grandChildTable As DataTable = GetGrandChildTable()
dSet.Tables.AddRange(New DataTable() {parentTable, childTable, grandChildTable})

'setup the relations


Dim parentColumn As DataColumn = parentTable.Columns("parentID")
Dim childColumn As DataColumn = childTable.Columns("ParentID")
dSet.Relations.Add("ParentToChild", parentColumn, childColumn)

parentColumn = childTable.Columns("childID")
childColumn = grandChildTable.Columns("ChildID")
dSet.Relations.Add("ChildToGrandChild", parentColumn, childColumn)

Me.TextBox1.DataBindings.Add("Text", parentTable, "ParentToChild.ChildToGrandChild.Name")

4.21 How do I call a SQL stored procedure?

You can call stored procedures in basically the same manner as executing other SQL commands.

When creating the SqlCommand, set the query string to be the name of the stored procedure, and then set
the CommandType to be CommandType.StoredProcedure.

if(sqlConn.State == ConnectionState.Closed)sqlConn.Open();

SqlCommand cmd = new SqlCommand("sp_my_stored_procedure",sqlConn);


cmd.CommandTimeout = 180;
cmd.CommandType = CommandType.StoredProcedure;

After you setup the command type, you need to pass in any parameters required for the stored procedure.
Here is an example of one input and one output parameter.

SqlParameter parm;

parm = cmd.Parameters.Add(new SqlParameter("@oid", SqlDbType.VarChar,50));


parm.Direction = ParameterDirection.Input;
cmd.Parameters["@oid"].Value = OrderID;
parm = cmd.Parameters.Add(new SqlParameter("@custName", SqlDbType.VarChar,50));
parm.Direction = ParameterDirection.Output;

If the stored procedure is returning a selection query at the end, you can fill your DataSet and retrieve any
tables.

SqlDataAdapter tempDA = new SqlDataAdapter();


tempDA.TableMappings.Add("your mapping","your mapping");
tempDA.SelectCommand = cmd;
DataSet dataSet1 = new DataSet();
tempDA.Fill(dataSet1);
DataTable resultTable = dataSet1.Tables[0];

Or, if no tables are being returned, you can execute the command as a non-query

cmd.ExecuteNonQuery();

4.22 I programatically change a bound TextBox value, but the value does not get pushed back into
the bound datasource. How can I make sure the DataSource is updated?

You can call the EndCurrentEdit method on the bindingmanager for the TextBox.

[C#]
this.textBox1.Text = "XXXX"; //set the value
this.textBox1.DataBindings["Text"].BindingManagerBase.EndCurrentEdit(); //end the edit

[VB.NET]
Me.TextBox1.Text = "XXXX"
<E.TEXTBOX1.DATABINDINGS("TEXT").BINDINGMANAGERBASE.ENDCURRENTEDIT()

4.23 Why does the CheckedListBox lose checked state when placed in a tab page that gets hidded and
shown?

In Usenet posts, MS has acknowledged this bug. The problem is essentially that any time the visibility
changes on a CheckedListBox, it loses its previous selections. Naturally this happens all the time in tab
controls when changing tabs. This derived Control saves it's state while getting hidden and reloads it while
getting shown:

[C#]
# region Workaround for CheckedListBox bug
//////////////////////////////////////////////////////////////////////
// When CheckedList box becomes invisible (e.g. when the tab page
// containing this control is overlapped with another tab page),
// checked state of the items are getting lost. This workaround will
// fix this problem
//////////////////////////////////////////////////////////////////////

private bool[] isItemChecked;


protected override void OnDataSourceChanged(EventArgs e)
{
base.OnDataSourceChanged(e);

int cnt = this.Items.Count;


isItemChecked = new Boolean[cnt];
for(int i = 0; i < cnt; i++)
{
isItemChecked[i] = GetItemChecked(i);
}
}

protected override void OnItemCheck(ItemCheckEventArgs e)


{
base.OnItemCheck(e);
isItemChecked[e.Index] = (e.NewValue == CheckState.Checked);
}

protected override void OnVisibleChanged(EventArgs e)


{
base.OnVisibleChanged(e);

if (this.Visible == true)
{
// Reset the checked states when it becomes visible.
for(int i =0; i < this.Items.Count; i++)
{
SetItemChecked(i, isItemChecked[i]);
}
}
}
#endregion

[VB.Net]
Public Class MyCheckedListBox
Inherits CheckedListBox
'////////////////////////////////////////////////////////////////////
' When CheckedList box becomes invisible (e.g. when the tab page
' containing this control is overlapped with another tab page),
' checked state of the items are getting lost. This workaround will
' fix this problem
'////////////////////////////////////////////////////////////////////
Private isItemChecked() As Boolean

Protected Overrides Sub OnDataSourceChanged(e As EventArgs)


MyBase.OnDataSourceChanged(e)

Dim cnt As Integer = Me.Items.Count


isItemChecked = New [Boolean](cnt) {}
Dim i As Integer
For i = 0 To cnt - 1
isItemChecked(i) = GetItemChecked(i)
Next i
End Sub 'OnDataSourceChanged

Protected Overrides Sub OnItemCheck(e As ItemCheckEventArgs)


MyBase.OnItemCheck(e)
isItemChecked(e.Index) = e.NewValue = CheckState.Checked
End Sub 'OnItemCheck

Protected Overrides Sub OnVisibleChanged(e As EventArgs)


MyBase.OnVisibleChanged(e)

If Me.Visible = True Then


' Reset the checked states when it becomes visible.
Dim i As Integer
For i = 0 To (Me.Items.Count) - 1
SetItemChecked(i, isItemChecked(i))
Next i
End If
End Sub 'OnVisibleChanged

End Class 'MyCheckedListBox

5. Windows Forms Datagrid FAQ Home


5.1 How can I programatically set the rowheight of a row in my DataGrid?
5.2 How can I autosize the rowheights in my datagrid?
5.3 How do I prevent sorting a single column in my DataGrid?
5.4 How do I programmatically select a row in DataGrid?
5.5 How can I translate a point to a cell in the datagrid?
5.6 I lost the settings in my DataGrid set during design-time?
5.7 How do I prevent a click into the grid highlighting a cell?
5.8 How do I prevent the datagrid from displaying its append row (the row at the end with an asterisk)?
5.9 How can I put a combobox in a column of a datagrid?
5.10 How can I catch a double-click into a column header cell?
5.11 How can I select the entire row when the user clicks on a cell in the row?
5.12 How can I get text from a column header in a MouseUp event?
5.13 How do I hide a column?
5.14 How do I color a individual cell depending upon its value or some external method?
5.15 How can I put a checkbox in a column of my DataGrid?
5.16 How can I restrict the keystrokes that will be accepted in a column of my datagrid?
5.17 How do I make a field auto increment as new rows are added to my datagrid?
5.18 How can I prevent a particular cell from being editable?
5.19 How do I move columns in a datagrid?
5.20 How can I do cell by cell validation in a datagrid?
5.21 How do I programmatically determine the selected rows in a datagrid?
5.22 How can I move rows by dragging the row header cell?
5.23 I want to do custom handling of special keys such as the Tab key or F2 in the TextBox of a column
in the DataGrid. How do I subclass this TextBox to get at it virtual members?
5.24 How can I have a column of icons in my datagrid?
5.25 How can I tell if the current row has changed and whether I am on the AddNew row or not?
5.26 How do I hide the gridlines or set them to a particular color?
5.27 How can I get the selected text in an active gridcell?
5.28 How do I determine whether a checkbox in my datagrid is checked or not?
5.29 How can I bind the datagrid to a datasource without using any wizards?
5.30 How can I bind two datagrids in a Master-Detail relationship?
5.31 How do I get the row or column that has been clicked on?
5.32 How do I add an unbound column to my bound datagrid?
5.33 How do I get the row and column of the current cell in my datagrid?
5.34 How can I prevent the Enter key from moving to the next cell when the user is actively editing the
cell and presses Enter?
5.35 How do I set the width of a column in my DataGrid?
5.36 How can I implement OLE Drag & Drop between a DataGrid and another OLE DnD object that
supports the Text format?
5.37 How can I make my DataGrid support a single select mode, and not the default multiselect mode?
5.38 How can I get celltips or tooltips to vary from cell to cell in my DataGrid?
5.39 How can I get notification of the changing of a value in a column of comboboxes within my
datagrid?
5.40 How can I make the datagrid have no currentcell?
5.41 How can I make my grid never have an active edit cell and always select whole rows (as in a
browser-type grid)?
5.42 I have hidden (column width = 0) columns on the right side of my datagrid, but tabbing does not
work properly. How can I get tabbing to work?
5.43 How can I get the number of rows in my DataGrid?
5.44 How do I format a date column in a datagrid?
5.45 How can I change the width of the row headers or hide them?
5.46 How do I catch a doubleclick in my datagrid?
5.47 How can I make my last column wide enough to exactly occupy all the client area of the datagrid?
5.48 How can I prevent my user from sizing columns in my datagrid?
5.49 How can I catch the bool values changing in a DataGridBoolColumn?
5.50 When I click on a row header, the row is selected and no cell is active. How can I do this
programmatically?
5.51 How can I force the vertical scrollbar in my DataGrid to always be visible?
5.52 How can I autosize a column in my datagrid?
5.53 How can I get rid of the error icon that appears when there is an editing error?
5.54 How do I find the top-left visible cell in a datagrid?
5.55 I want to display negative values with a CR suffix, instead of a minus sign. How can I perform
custom formatting on the cells in my datagrid?
5.56 I want to do sort of a database join of two tables. How can I use data from two DataTables in a
single DataGrid?
5.57 How do I display a column of buttons such as pushbuttons or combobox buttons?
5.58 How can I put up a confirmation question when the user tries to delete a row in the datagrid by
clicking on the row header and pressing the Delete key?
5.59 How can I enable column selections in my datagrid?
5.60 How do I programmatically scroll the datagrid to a particular row?
5.61 How can I place text in the rowheader column of my datagrid?
5.62 How do I set default values for new rows in my datagrid?
5.63 How do I iterate through all the rows and columns in my datagrid?
5.64 How can I specially color only the currentcell of my readonly datagrid?
5.65 How can I make the Enter Key behave like the Tab Key and move to the next cell?
5.66 How do I use the DataColumn.Expression property to add a computed/combined column to my
datagrid?
5.67 How can I change the font used in a grid cell on a cell by cell or row by row basis?
5.68 How can I use a mouse to select cell ranges in my datagrid?
5.69 How can I control the cursor over my DataGrid?
5.70 How can I programatically add and remove columns in my DataGrid without modifying the
DataTable datasource?
5.71 How can I have a column of bitmaps in a DataGrid?
5.72 How can I add my custom columnstyles to the designer so I can use them in my DataGrid at design
time?
5.73 After scrolling with the mouse wheel on a selected row in a DataGrid I cannot get it back into view.
Is there a work around?
5.74 How can I make the DataGrid column be blank and not display (null) as the default value?
5.75 How can I add a DateTimePicker column style to the DataGrid?
5.76 How do I determine the DataGridTableStyle MappingName that should used for a DataGrid to
make sure the grid uses my tablestyle?
5.77 I have a derived DataGridColumnStyle. From within my Paint override, how can I get at other
values in the DataGrid?
5.78 How do I retrieve the current row from a DataTable bound to a DataGrid after the grid has been
sorted?
5.79 How can I catch when the user clicks off the grid, say to close the form?
5.80 How can I get a CheckBox column in a DataGrid to react to the first click?
5.81 How can I use events to restrict key input to grid cells?
5.82 How can I format columns in my DataGrid without explicilty adding DataGridColumnStyles?
5.83 How can I auto-adjust keyboard input? For example, make typing 12312002 be taken as a valid
date, 12/31/2002.
5.84 Can I display the rows in my datagrid in a free-form layout using textboxes on a panel?
5.85 How can I tell whether a scrollbar is visible in my DataGrid is visible?
5.86 How do I autosize the columns in my DataGrid so they always fill the the grid's client area?
5.87 How can I prevent all the cells in my DataGrid from being edited without deriving
GridColumnStyle?
5.88 How can I prevent the plus-minus icon that appears next to the row header when I have a datagrid
displayed bound to a datasource that has a relation defined?
5.89 How can I display master-details-details in three separate grids?
5.90 In my datagrid, if I press tab to enter a column using a derived columnstyle, the column does not
receive focus. Why?
5.91 How can I detect when a cell starts being edited, not when it becomes current?

5.1 How can I programatically set the rowheight of a row in my DataGrid?

One way you can do this is to use reflection to access the DataGrid internal row objects which are not
publicly exposed. This solution was suggested by Matthew Benedict in a private communication.

Here are both VB and C# sample projects showing how you might do this. The sample provides a class that
you can instantiate by passing a DataGrid, creating a rowHeights object. Once you create this object, you
can use an indexer on the object to set and get the rowheights.

5.2 How can I autosize the rowheights in my datagrid?

Here is a solution suggested by Matthew Benedict. It uses reflection to access the protected DataGridRows
collection so he can set the row height.

public void AutoSizeGrid()


{
// DataGrid should be bound to a DataTable for this part to
// work.
int numRows = ((DataTable)gridTasks.DataSource).Rows.Count;
Graphics g = Graphics.FromHwnd(gridTasks.Handle);
StringFormat sf = new StringFormat(StringFormat.GenericTypographic);
SizeF size;

// Since DataGridRows[] is not exposed directly by the DataGrid


// we use reflection to hack internally to it.. There is actually
// a method get_DataGridRows that returns the collection of rows
// that is what we are doing here, and casting it to a System.Array
MethodInfo mi = gridTasks.GetType().GetMethod("get_DataGridRows",
BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase | BindingFlags.Instance
| BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);

System.Array dgra = (System.Array)mi.Invoke(gridTasks,null);

// Convert this to an ArrayList, little bit easier to deal with


// that way, plus we can strip out the newrow row.
ArrayList DataGridRows = new ArrayList();
foreach (object dgrr in dgra)
{
if (dgrr.ToString().EndsWith("DataGridRelationshipRow")==true)
DataGridRows.Add(dgrr);
}

// Now loop through all the rows in the grid


for (int i = 0; i < numRows; ++i)
{
// Here we are telling it that the column width is set to
// 400.. so size will contain the Height it needs to be.
size = g.MeasureString(gridTasks[i,1].ToString(),gridTasks.Font,400,sf);
int h = Convert.ToInt32(size.Height);
// Little extra cellpadding space
h = h + 8;

// Now we pick that row out of the DataGridRows[] Array


// that we have and set it's Height property to what we
// think it should be.
PropertyInfo pi = DataGridRows[i].GetType().GetProperty("Height");
pi.SetValue(DataGridRows[i],h,null);

// I have read here that after you set the Height in this manner that you should
// Call the DataGrid Invalidate() method, but I haven't seen any prob with not calling it..

g.Dispose();
}

5.3 How do I prevent sorting a single column in my DataGrid?

You can do this by deriving the DataGrid and overriding OnMouseDowm. In your override, do a HitText
and if the hit is on a column header that you do not want to sort, do not call the baseclass. Here is a code
that sorts all columns except the second column

[C#]
//derived class
public class MyDataGrid : DataGrid
{
protected override void OnMouseDown(MouseEventArgs e)
{
Point pt = new Point(e.X, e.Y);
DataGrid.HitTestInfo hti = this.HitTest(pt);
if(hti.Type == HitTestType.ColumnHeader && hti.Column == 1)
{
//don't sort col 1
return; //don't call baseclass
}
base.OnMouseDown(e);
}
}

[VB.NET]
'derived class
Public Class MyDataGrid
Inherits DataGrid
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
Dim pt As New Point(e.X, e.Y)
Dim hti As DataGrid.HitTestInfo = Me.HitTest(pt)
If hti.Type = HitTestType.ColumnHeader AndAlso hti.Column = 1 Then
'don't sort col 1
Return 'don't call baseclass
End If
MyBase.OnMouseDown(e)
End Sub 'OnMouseDown
End Class 'MyDataGrid

5.4 How do I programmatically select a row in DataGrid?

To progamatically select a row, you need to call:

[C#]
//select row 1
this.dataGrid1.Select(1);
[VB.NET]
'select row 1
Me.dataGrid1.Select(1)

5.5 How can I translate a point to a cell in the datagrid?

If the point, say pt, is in screen coordinates, you can use code such as

Point p1 = dataGrid1.PointToClient(pt);
MessageBox.Show(dataGrid1.HitTest(p1).ToString());

If you are using context menus for catching right-clicks in the grid, you have to do a little work to
remember where the original right-click point was as the point passed in through the menu event arguments
may not reflect this original click. One solution is to remember the click in the grid MouseDown event, and
then use the code above to retrieve the grid cell from within the menu handler.

Point rightMouseDownPoint;

private void dataGrid1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)


{
if(e.Button == MouseButtons.Right)
rightMouseDownPoint = Cursor.Position;
}

private void menuItem4_Click(object sender, System.EventArgs e)


{
Point pt = dataGrid1.PointToClient(rightMouseDownPoint);
MessageBox.Show(dataGrid1.HitTest(pt).ToString());
}

5.6 I lost the settings in my DataGrid set during design-time?

This is possible if you assign a custom DataGridTableStyle to the DataGrid. The properties in the
DataGridTableStyle will then replace certain properties in the DataGrid. Take a look at DataGrid class
reference for a list of these properties.

5.7 How do I prevent a click into the grid highlighting a cell?

Set the grid's Enabled property to false.

dataGrid1.Enabled = false;

5.8 How do I prevent the datagrid from displaying its append row (the row at the end with an asterisk)?

The DataGrid class does not have a property that controls whether a new row can be added. But the
DataView class does have such a property (along with some others such as AllowEdit and AllowDelete).
Here is code that will turn off the append row by getting at the dataview associated with the datagrid.

string connString = @"Provider=Microsoft.JET.OLEDB.4.0;data source=C:\northwind.mdb";


string sqlString = "SELECT * FROM customers";

// Connection object
OleDbConnection connection = new OleDbConnection(connString);

// Create data adapter object


OleDbDataAdapter dataAdapter = new OleDbDataAdapter(sqlString, connection);

// Create a dataset object and fill with data using data adapter's Fill method
DataSet dataSet = new DataSet();
dataAdapter.Fill(dataSet, "customers");

// Attach dataset's DefaultView to the datagrid control


dataGrid1.DataSource = dataSet.Tables["customers"];

//no adding of new rows thru dataview...


CurrencyManager cm = (CurrencyManager)this.BindingContext[dataGrid1.DataSource,
dataGrid1.DataMember];
((DataView)cm.List).AllowNew = false;

If your datagrid contains links, then Matthew Miller suggest adding Navigate handler such as the one below
to disallow the AddNew.
private void DataGrid1_Navigate(object sender, System.Windows.Forms.NavigateEventArgs ne)
{
if(ne.Forward)
{
CurrencyManager cm =
(CurrencyManager)BindingContext[DataGrid1.DataSource,DataGrid1.DataMember];
DataView dv = (DataView) cm.List;
dv.AllowNew = false;
}
}
5.9 How can I put a combobox in a column of a datagrid?

There are several ways to go about this task. The simplest way involves adding a single combobox to the
DataGrid.Controls, and then selectively displaying it as needed when a combobox cell becomes the
currentcell. All the work is done in a few event handlers and no overrides or derived classes are necessary.
This technique is discussed in Microsoft KB article Q323167.

The other techniques require you to derive a columnstyle. Attached is a dropdown combobox sample (C#,
VB) that shows how you can use a combobox in a datagrid. This implementation differs from other
available columnstyle samples (gotdotnet.com and C# Corner ) in that it derives from
DataGridTextBoxColumn. These other samples derive directly from DataGridColumnStyle, and thus have
to add functionality that already exists in DataGridTextBoxColumn.

This derived DataGridTextBoxColumn does not implement a databound combobox where you can set its
DataSource, DisplayMember, and ValueMember to bind the combobox to a foreign table. If you need such
a combobox, there is another sample link referenced at the end of this FAQ that does implement such a
databound combobox.

This sample just attempts to replace the TextBox member of DataGridTextBoxColumn with a standard
ComboBox member. Only two overrides need to be handled along with 2 events to get a functional
implementation.

Here are the notes from the code that list the 3 steps to add a combobox to your datagrid.

// Step 1. Derive a custom column style from DataGridTextBoxColumn


// a) add a ComboBox member
// b) track when the combobox has focus in Enter and Leave events
// c) override Edit to allow the ComboBox to replace the TextBox
// d) override Commit to save the changed data

// Step 2 - Use the combo column style


// Add 1 col with combo style
DataGridComboBoxColumn ComboTextCol = new DataGridComboBoxColumn();
ComboTextCol.MappingName = "custCity";
ComboTextCol.HeaderText = "Customer Address";
ComboTextCol.Width = 100;
ts1.GridColumnStyles.Add(ComboTextCol);

// Step 3 - Additional setup for Combo style


// a) make the row height a little larger to handle minimum combo height
ts1.PreferredRowHeight = ComboTextCol.ColumnComboBox.Height + 3;
// b) Populate the combobox somehow. It is a normal combobox, so whatever...
ComboTextCol.ColumnComboBox.Items.Clear();
ComboTextCol.ColumnComboBox.Items.Add("Chicago");
ComboTextCol.ColumnComboBox.Items.Add("Corvallis");
ComboTextCol.ColumnComboBox.Items.Add("Denver");
ComboTextCol.ColumnComboBox.Items.Add("Great Falls");
ComboTextCol.ColumnComboBox.Items.Add("Kansas City");
ComboTextCol.ColumnComboBox.Items.Add("Los Angeles");
ComboTextCol.ColumnComboBox.Items.Add("Raleigh");
ComboTextCol.ColumnComboBox.Items.Add("Washington");

// c) set the dropdown style of the combo...


ComboTextCol.ColumnComboBox.DropDownStyle = ComboBoxStyle.DropDownList;

Databound ComboBox Sample


To use a databound combobox, you have to add overrides for SetColumnValueAtRow and
GetColumnValueAtRow to switch the DisplayMember and ValueMember as you get and set the data from
the underlying table. Also, you cannot have the ComboBox bound with the same BindingContext to the
same datasource as the datagrid. You can download a working project (C#, VB) that implements a
databound combobox in a datagrid.

Thanks to Gerald Walsh for his suggestion to use the ComboBox.SelectionChangeCommitted event to set
the editing flag within our derived columnstyle class.

5.10 How can I catch a double-click into a column header cell?

You can use the DataGrid's double-click event and its HitTest method to catch a double click on a header.

private void dataGrid1_DoubleClick(object sender, System.EventArgs e)


{
System.Drawing.Point pt = dataGrid1.PointToClient(Cursor.Position);

DataGrid.HitTestInfo hti = dataGrid1.HitTest(pt);

if(hti.Type == DataGrid.HitTestType.ColumnHeader)
{
MessageBox.Show("double clicked clicked column header " + hti.Column.ToString());
}
}

5.11 How can I select the entire row when the user clicks on a cell in the row?

Call the DataGrid.Select method from within its mouseup event.


[C#]
private void dataGrid1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
System.Drawing.Point pt = new Point(e.X, e.Y);
DataGrid.HitTestInfo hti = dataGrid1.HitTest(pt);
if(hti.Type == DataGrid.HitTestType.Cell)
{
dataGrid1.CurrentCell = new DataGridCell(hti.Row, hti.Column);
dataGrid1.Select(hti.Row);
}
}

[VB/NET]
Private Sub dataGrid1_MouseUp(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles dataGrid1.MouseUp
Dim pt = New Point(e.X, e.Y)
Dim hti As DataGrid.HitTestInfo = dataGrid1.HitTest(pt)
If hti.Type = DataGrid.HitTestType.Cell Then
dataGrid1.CurrentCell = New DataGridCell(hti.Row, hti.Column)
dataGrid1.Select(hti.Row)
End If
End Sub

5.12 How can I get text from a column header in a MouseUp event?

private void dataGrid1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)


{
System.Drawing.Point pt = new Point(e.X, e.Y);
DataGrid.HitTestInfo hti = dataGrid1.HitTest(pt);
if(hti.Type == DataGrid.HitTestType.Cell)
{
MessageBox.Show(dataGrid1[hti.Row, hti.Column].ToString());
}
else if(hti.Type == DataGrid.HitTestType.ColumnHeader)
{
MessageBox.Show(((DataView) DataGrid1.DataSource).Table.Columns[hti.Column].ToString());
}
}

5.13 How do I hide a column?

There are several ways to hide a column:

1) You can use your DataSet's ColumnMapping property to hide a column.


// Creating connection and command sting
string conStr = @"Provider=Microsoft.JET.OLEDB.4.0;data source=C:\northwind.mdb";
string sqlStr = "SELECT * FROM Employees";
// Create connection object
OleDbConnection conn = new OleDbConnection(conStr);
// Create data adapter object
OleDbDataAdapter da = new OleDbDataAdapter(sqlStr,conn);

// Create a dataset object and fill with data using data adapter's Fill method
DataSet ds = new DataSet();
da.Fill(ds, "Employees");

// Hide the column and attach dataset's DefaultView to the datagrid control
ds.Tables["Employees"].Columns["LastName"].ColumnMapping = MappingType.Hidden;
dataGrid1.DataSource = ds.Tables["Employees"];

2) Another way to hide a column is to set its width to zero. Check out the FAQ How do I set the width of a
column in my DataGrid?.

3) Another way to hide a column is to create a custom table style, and as you add columnstyles to your
tablestyle, omit the column you want hidden. Check out the FAQ How do I add an unbound column in my
bound DataGrid? to see how to create a custom table style.

5.14 How do I color a individual cell depending upon its value or some external method?

We give three different methods for doing this.

The first one overrides Paint in a derived columnstyle and sets the backcolor there.
The second uses a delegate to set the color in the Paint override.
The third method adds an event to the derived column style to allow you to set the color in an event
handler.

Method 1
You can do this by deriving from DataGridTextBoxColumn and overriding the Paint method to
conditionally set the backColor and foreColor. The sample code below colors any cell that starts with a
letter higher than 'F'. You can download a project (C#, VB) using this class.
[C#]
public class DataGridColoredTextBoxColumn : DataGridTextBoxColumn
{
protected override void Paint(System.Drawing.Graphics g,
System.Drawing.Rectangle bounds, System.Windows.Forms.CurrencyManager
source, int rowNum, System.Drawing.Brush backBrush, System.Drawing.Brush
foreBrush, bool alignToRight)
{
// the idea is to conditionally set the foreBrush and/or backbrush
// depending upon some crireria on the cell value
// Here, we color anything that begins with a letter higher than 'F'
try{
object o = this.GetColumnValueAtRow(source, rowNum);
if( o!= null)
{
char c = ((string)o)[0];
if( c > 'F')
{
// could be as simple as
// backBrush = new SolidBrush(Color.Pink);
// or something fancier...
backBrush = new LinearGradientBrush(bounds,
Color.FromArgb(255, 200, 200),
Color.FromArgb(128, 20, 20),
LinearGradientMode.BackwardDiagonal);
foreBrush = new SolidBrush(Color.White);
}
}
}
catch(Exception ex){ /* empty catch */ }
finally{
// make sure the base class gets called to do the drawing with
// the possibly changed brushes
base.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight);
}
}
}

[VB.NET}
Public Class DataGridColoredTextBoxColumn
Inherits DataGridTextBoxColumn

Public Sub New()


End Sub

Protected Overloads Overrides Sub Paint(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal
source As CurrencyManager, ByVal rowNum As Integer, ByVal backBrush As Brush, ByVal foreBrush As
Brush, ByVal alignToRight As Boolean)

' the idea is to conditionally set the foreBrush and/or backbrush


' depending upon some crireria on the cell value
' Here, we color anything that begins with a letter higher than 'F'
Try
Dim o As Object
o = Me.GetColumnValueAtRow(source, rowNum)
If (Not (o) Is Nothing) Then
Dim c As Char
c = CType(o, String).Substring(0, 1)
If (c > "F") Then
' could be as simple as
' backBrush = new SolidBrush(Color.Pink);
' or something fancier...
backBrush = New LinearGradientBrush(bounds, Color.FromArgb(255, 200, 200),
Color.FromArgb(128, 20, 20), LinearGradientMode.BackwardDiagonal)
foreBrush = New SolidBrush(Color.White)
End If
End If
Catch ex As Exception
' empty catch
Finally
' make sure the base class gets called to do the drawing with
' the possibly changed brushes
MyBase.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight)
End Try

End Sub
End Class

Method 2
To use some method to provide the cell color, you can use a similar technique as discussed above. But
instead of setting the color based on cell value, call a delegate method instead. This delegate can be passed
in using the constructor for the custom column style. You can download a sample that shows how this can
be done.

Method 3
If you want a more flexible solution, you could expose an event as part of your derived columnstyle that
fires in the Paint override. This would allow the handler of the event to set the color value depending upon
the row and column parameters that are passed as part of the event args. You can download a sample (C#,
VB) that implements this technique. The sample actually handles allowing a cell to be editable on a cell by
cell basis through an event. This sample colors the back ground of the disabled cell gray. You could modify
the eventargs to include a backcolor, and use this event to color cells based on row and column values
removing the event call in the Edit override.

5.15 How can I put a checkbox in a column of my DataGrid?

You create a custom DataTableStyle that contains column styles for each column you want to display. You
add the column styles in the order you want them to appear. Here are the steps to add an string column, an
int column and a bool check column to a DataGrid. You can also download a working project.

// code assumes you have a DataSet named myDataSet, a table named "EastCoastSales" and a DataGrid
myDataGrid
//STEP 1: Create a DataTable style object and set properties if required.
DataGridTableStyle ts1 = new DataGridTableStyle();

//specify the table from dataset (required step)


ts1.MappingName = "EastCoastSales";

// Set other properties (optional step)


ts1.AlternatingBackColor = Color.LightBlue;
//STEP 2: Create a string column and add it to the tablestyle
DataGridColumnStyle TextCol = new DataGridTextBoxColumn();
TextCol.MappingName = "custName"; //from dataset table
TextCol.HeaderText = "Customer Name";
TextCol.Width = 250;
ts1.GridColumnStyles.Add(TextCol);

//STEP 3: Create an int column style and add it to the tablestyle


//this requires setting the format for the column through its property descriptor
PropertyDescriptorCollection pdc = this.BindingContext
[myDataSet, "EastCoastSales"].GetItemProperties();

//now created a formated column using the pdc


DataGridDigitsTextBoxColumn csIDInt =
new DataGridDigitsTextBoxColumn(pdc["CustID"], "i", true);
csIDInt.MappingName = "CustID";
csIDInt.HeaderText = "CustID";
csIDInt.Width = 100;
ts1.GridColumnStyles.Add(csIDInt);

//STEP 4: Add the checkbox


DataGridColumnStyle boolCol = new DataGridBoolColumn();
boolCol.MappingName = "Current";
boolCol.HeaderText = "Info Current";

//uncomment this line to get a two-state checkbox


//((DataGridBoolColumn)boolCol).AllowNull = false;

boolCol.Width = 150;
ts1.GridColumnStyles.Add(boolCol);

//STEP 5: Add the tablestyle to your datagrid's tablestlye collection


myDataGrid.TableStyles.Add(ts1);

5.16 How can I restrict the keystrokes that will be accepted in a column of my datagrid?

You can create a custom column style and handle the KeyPress event of its TextBox member. Below is the
code showing how this might be done. You can also download a sample project (C#, VB) that shows an
implementation of this idea.

public class DataGridDigitsTextBoxColumn : DataGridTextBoxColumn


{
public DataGridDigitsTextBoxColumn(System.ComponentModel.PropertyDescriptor pd, string format,
bool b)
: base(pd, format, b)
{
this.TextBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(HandleKeyPress);
}

private void HandleKeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)


{
//ignore if not digit or control key
if(!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar))
e.Handled = true;

//ignore if more than 3 digits


if(this.TextBox.Text.Length >= 3 && !char.IsControl(e.KeyChar))
e.Handled = true;
}

protected override void Dispose(bool disposing)


{
if(disposing)
this.TextBox.KeyPress -= new
System.Windows.Forms.KeyPressEventHandler(HandleKeyPress);

base.Dispose(disposing);
}
}

5.17 How do I make a field auto increment as new rows are added to my datagrid?

DataTable myTable = new DataTable("Customers");


...
DataColumn cCustID = new DataColumn("CustID", typeof(int));
cCustID.AutoIncrement = true;
cCustID.AutoIncrementSeed = 1;
cCustID.AutoIncrementStep = 1;
myTable.Columns.Add(cCustID);

5.18 How can I prevent a particular cell from being editable?

You can do this by deriving a custom column style and overriding its virtual Edit member. Below is an
override that will prevent the cell in row 1 of the column from getting the edit focus. You can paste this
code in the DataGridDigitsTextBoxColumn sample to see it work.

If you want a more flexible solution, you could expose an event as part of your derived columnstyle that
fires right before the call to the baseclass in the Edit override. This would allow the handler of the event to
set the enable value depending upon the row and column parameters that are passed as part of the event
args. You can download a sample (C#, VB) that implements this technique. The sample also fires the event
right before painting the cell to decide whether to paint a gray background for the disabled cell. You could
modify the eventargs to include a backcolor, and use this event to color cells based on row and column
values.
//this override will prevent the cell in row 1 from getting the edit focus
protected override void Edit(System.Windows.Forms.CurrencyManager source, int rowNum,
System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
{
if(rowNum == 1)
return;
base.Edit(source, rowNum, bounds, readOnly, instantText, cellIsVisible);
}
5.19 How do I move columns in a datagrid?

The columns appear in the order that their column styles were added to the tablestyle being used by the
grid. If you want to change this order, you would need to create a new table style, and add the columnstyles
in the order you want thiings to appear. Here is some code snippets that suggest how to do this.

[C#]
public void MoveColumn(DataGrid _dataGrid, string _mappingName, int fromCol, int toCol)
{
if(fromCol == toCol) return;

DataGridTableStyle oldTS = _dataGrid.TableStyles[_mappingName];


DataGridTableStyle newTS = new DataGridTableStyle();
newTS.MappingName = _mappingName;

for(int i = 0; i < oldTS.GridColumnStyles.Count; ++i)


{
if(i != fromCol && fromCol < toCol)
newTS.GridColumnStyles.Add(oldTS.GridColumnStyles[i]);
if(i == toCol)
newTS.GridColumnStyles.Add(oldTS.GridColumnStyles[fromCol]);
if(i != fromCol && fromCol > toCol)
newTS.GridColumnStyles.Add(oldTS.GridColumnStyles[i]);
}

_dataGrid.TableStyles.Remove(oldTS);
_dataGrid.TableStyles.Add(newTS);
}

//sample usage
private void button1_Click(object sender, System.EventArgs e)
{
MoveColumn(myDataGrid, "Customers", 3, 1);
}

[VB.NET]
Public Sub MoveColumn(_dataGrid As DataGrid, _mappingName As String, fromCol As Integer, toCol As
Integer)
If fromCol = toCol Then
Return
End If
Dim oldTS As DataGridTableStyle = _dataGrid.TableStyles(_mappingName)
Dim newTS As New DataGridTableStyle()
newTS.MappingName = _mappingName

Dim i As Integer
i=0
While i < oldTS.GridColumnStyles.Count
If i <> fromCol And fromCol < toCol Then
newTS.GridColumnStyles.Add(oldTS.GridColumnStyles(i))
End If
If i = toCol Then
newTS.GridColumnStyles.Add(oldTS.GridColumnStyles(fromCol))
End If
If i <> fromCol And fromCol > toCol Then
newTS.GridColumnStyles.Add(oldTS.GridColumnStyles(i))
End If
i=i+1
End While
_dataGrid.TableStyles.Remove(oldTS)
_dataGrid.TableStyles.Add(newTS)
End Sub 'MoveColumn

'sample usage
Private Sub button1_Click(sender As Object, e As System.EventArgs)
MoveColumn(myDataGrid, "Customers", 3, 1)
End Sub 'button1_Click

5.20 How can I do cell by cell validation in a datagrid?

There are problems trying to implement cell by cell validation using the grid's Validating event architecture.
The problem is that the grid is not the object handling the data. Instead, a TextBox or some other control is
the control managing the changing of the cell contents. One way to implement the validation at the grid
level is to handle the CurrentCellChanged event, and if the previous cell's value is not proper, then return to
that cell. You can download a sample that implements this process. The sample only handles the validation
from cell to cell movement. If you want to handle the validation when the user clicks on the forms Close
button, then you would have to add a special event handler for this and do one last validation at this point.

5.21 How do I programmatically determine the selected rows in a datagrid?

The method DataGrid.IsSelected can tell you if a particular row is selected. So, you could use IsSelected in
a loop through all your rows to finds if multiple rows have been selected. Depending upon the size of your
datagrid, this may be a viable solution. If not, you could track the selections yourself by monitoring the key
actions and the mouse actions. This would be more work. Thanks to John Hughes to the suggestion to use
the dataview.

[C#]
public ArrayList GetSelectedRows(DataGrid dg)
{
ArrayList al = new ArrayList();
CurrencyManager cm = (CurrencyManager)this.BindingContext[dg.DataSource, dg.DataMember];
DataView dv = (DataView)cm.List;

for(int i = 0; i < dv.Count; ++i)


{
if(dg.IsSelected(i))
al.Add(i);
}
return al;
}

private void button1_Click(object sender, System.EventArgs e)


{
string s = "Selected rows:";
foreach(object o in GetSelectedRows(dataGrid1))
{
s+=""+o.ToString();
}
MessageBox.Show(s);
}

[VB.NET]
Public Function GetSelectedRows(ByVal dg As DataGrid) As System.Collections.ArrayList
Dim al As New ArrayList()

Dim cm As CurrencyManager = Me.BindingContext(dg.DataSource, dg.DataMember)


Dim dv As DataView = CType(cm.List, DataView)

Dim i As Integer
For i = 0 to dv.Count - 1
If dg.IsSelected(i) Then
al.Add(i)
End If
End Next
Return al
End Function 'GetSelectedRows

Private Sub button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles


Button1.Click
Dim s As String = "Selected rows:"
Dim o As Object
For Each o In GetSelectedRows(dataGrid1)
s += " " + o.ToString()
Next o
MessageBox.Show(s)
End Sub 'button1_Click

5.22 How can I move rows by dragging the row header cell?
One way to implement this is to derive a DataGrid and override the virtual OnMouseDown,
OnMouseMove and OnMouseUp methods. In your overrides, if the mousedown is on a row header, track
the initial mousedown row, and as it moves, draw a line to indicate a target position. Then on the mouseup,
handle moving the row.

You can download a sample (C#, VB) that illustrates how this might be done.

5.23 I want to do custom handling of special keys such as the Tab key or F2 in the TextBox of a column in
the DataGrid. How do I subclass this TextBox to get at it virtual members?

The TextBox property of the DataGridTextBoxColumn is ReadOnly, so you just cannot set a new derived
TextBox into it. One solution is to derive a TextBox, and then have it use the derived TextBox in the
DataGridTextBoxColumn instead of the 'generic' TextBox that is there. This is the same technique used in
our combobox in a column sample. In that sample, the generic textbox was 'replaced' with a combobox.
Here, we replace it with a derived TextBox where we can easily override virtual members.

A reasonable question is why not just use the event mechanism of the existing TextBox to modify behavior.
Events like KeyPress would allow us to do some things PROVIDED they get hit. Due to the key processing
architecture of the FrameWork, for some special keys, these key events are not always fired. And if they are
fired, sometimes it is impossible to avoid the default processing if this is the intent you have. Overriding a
virtual function, doing something special, and then NOT calling the baseclass is a standard way of avoiding
default processing.

In this sample (both VB and CS), we override PreProcessMessage and avoid processing the Keys.Tab key.
You can modify the code to not process Keys.F2 as well. DataGridTextBoxColumn is subclassed so it can
use our derived TextBox.

5.24 How can I have a column of icons in my datagrid?

You need to derive a custom column style, override its Paint method and draw the image. In the attached
samples, (VB and C#), there are two custom column styles. One style is a stand-alone unbound column that
just displays an image. The second custom column style adds the image to the left side of a bound column.
In both cases, the actual image that is displayed is from an imagelist passed into the column in its
constructor. The index of the image to be drawn on a particular row is determined by a delegate passed into
the column style through its constructor.

5.25 How can I tell if the current row has changed and whether I am on the AddNew row or not?

The DataGrid's CurrentCellChanged event is hit even if you just change cells in the current row. If you
want an event that is only hit when you change rows, then you have to look at the binding manager. This
object has both a CurrentChanged event and a PositionChanged event which are hit when you change rows.

To decide whether you are on the AddNew row or not, you can again use the binding manager and compare
the number of rows it returns with the number of rows in your data table. Below is some code snippets
showing how you might get at this information.
private System.Windows.Forms.DataGrid dataGrid1;
private BindingManagerBase bindingManager;

private void Form1_Load(object sender, System.EventArgs e)


{
// Creating connection and command sting
string conStr = @"Provider=Microsoft.JET.OLEDB.4.0;data source=C:\northwind.mdb";
string sqlStr = "SELECT * FROM Employees";
// Create connection object
OleDbConnection conn = new OleDbConnection(conStr);
// Create data adapter object
OleDbDataAdapter da = new OleDbDataAdapter(sqlStr,conn);

// Create a dataset object and fill with data using data adapter's Fill method
DataSet ds = new DataSet();
da.Fill(ds, "Employees");
dataGrid1.DataSource = ds.Tables["Employees"];
bindingManager = this.BindingContext[dataGrid1.DataSource];
bindingManager.PositionChanged += new System.EventHandler(RowChanged);
}

private void RowChanged(object sender, System.EventArgs e)


{
Console.WriteLine("RowChanged " + bindingManager.Position.ToString() );
bool lastRow = bindingManager.Count > ((DataTable)dataGrid1.DataSource).Rows.Count;

if(lastRow)
Console.WriteLine("lastRow");
}

5.26 How do I hide the gridlines or set them to a particular color?

If your datagrid does not have a custom TableStyle associated with it, then there are two DataGrid
properties that control the color and visibility of the gridlines.

DataGrid..GridLineColor
DataGrid.GridLineStyle

If you have a custom TableStyle. you need to set the color within the TableStyle. Here is code that makes
the line color the same as the background color, and hence hides the gridlines. You can download a sample.

private void Form1_Load(object sender, System.EventArgs e)


{
// Set the connection and sql strings
// assumes your mdb file is in your root
string connString = @"Provider=Microsoft.JET.OLEDB.4.0;data source=C:\northwind.mdb";
string sqlString = "SELECT * FROM customers";

OleDbDataAdapter dataAdapter = null;


DataSet _dataSet = null;

try
{
// Connection object
OleDbConnection connection = new OleDbConnection(connString);

// Create data adapter object


dataAdapter = new OleDbDataAdapter(sqlString, connection);

// Create a dataset object and fill with data using data adapter's Fill method
_dataSet = new DataSet();
dataAdapter.Fill(_dataSet, "customers");
connection.Close();
}
catch(Exception ex)
{
MessageBox.Show("Problem with DB access-\n\n connection: "
+ connString + "\r\n\r\n query: " + sqlString
+ "\r\n\r\n\r\n" + ex.ToString());
this.Close();
return;
}

// Create a table style that will hold the new column style
// that we set and also tie it to our customer's table from our DB
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = "customers";
tableStyle.GridLineColor = dataGrid1.BackColor;

dataGrid1.TableStyles.Add(tableStyle);
dataGrid1.DataSource = _dataSet.Tables["customers"];

5.27 How can I get the selected text in an active gridcell?

You need to get the DataGridTextBoxColumn.TextBox member, and retrieve the SelectedText from it for
the active cell. The sample shows how you can do this as part of handling this TextBox's rightClick. This
code assumes you have specifically added DataGridTextBoxColumn for each column style. You can also
download a VB sample.

private void HandleMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)


{
if(e.Button == MouseButtons.Right)
{
DataGridTableStyle ts = dataGrid1.TableStyles["customers"];
DataGridTextBoxColumn cs =
(DataGridTextBoxColumn)ts.GridColumnStyles[dataGrid1.CurrentCell.ColumnNumber];
MessageBox.Show("Selected: " + cs.TextBox.SelectedText);
}
}

5.28 How do I determine whether a checkbox in my datagrid is checked or not?

If the column is a boolean column, you can just cast the object returned by the indexer to a bool and use it.

if((bool)dataGridTopics[row, column])
MessageBox.Show("I am true");
else
MessageBox.Show("I am false");

5.29 How can I bind the datagrid to a datasource without using any wizards?

Here is a really simple data binding sample. Just drag and drop a datagrid onto a default Windows Forms
application. Follow the steps below to bind this grid to the NorthWind db in SQL server.

Complete Sample: simpledata.zip

// Create a connection
SqlConnection connection = new SqlConnection(this.GetConnectionString());

// Create a data adapter. Think of the data adapter as an object that knows how to get the data from the
// data source into a dataset
SqlDataAdapter dataAdapter = new SqlDataAdapter(this.GetCommandText(), connection);

// fill the dataset using the data adapter


DataSet dataSet = new DataSet("Customers");
dataAdapter.Fill(this.dataSet, "Customers");

// bind to the grid


grid.DataSource = this.dataSet; // the big picture
grid.DataMember = "Customers"; // the specific table that we want to bind to

// The connection text looks like this


// If your SQL server is running on the default port, you can remove the port attribute.
private string GetConnectionString()
{
string server = "your_server_name";
string serverPort = "port_address";
string catalog = "NorthWind";
string password = "user_pass";
string userId = "user_name";

string connectionString = "data source={0},{1};initial catalog={2};" +


"password={3}; user id={4}; packet size=4096";

return string.Format(connectionString,
server, serverPort, catalog, password, userId);
}

// The command text looks like this

private string GetCommandText()


{
string commandText = "Select * from customers";
return commandText;
}

5.30 How can I bind two datagrids in a Master-Detail relationship?

Please download this sample before reading the rest of this FAQ. Looking through the sample will help
follow the description.

simpledata2.zip

What this boils down to is this:


1) Load both Master and Details queries in a dataset.

// I am using the SQL server NorthWind database


this.dataAdapterMaster.Fill(this.dataSet, "Customers");
this.dataAdapterDetails.Fill(this.dataSet, "Orders");

2) Bind the master data grid to the Master dataset table.

// The master view


grid.DataSource = this.dataSet;
grid.DataMember = "Customers";

3) Create a relationship that describes how the two tables relate to each other. A primary key foriegn key
relationship is defined by two attributes.
The primary key column in the master table
The foreign key coumn in the details table
The created relationship is added to the dataset.

this.dataSet.Relations.Add("CustomersToOrders",
dataSet.Tables["Customers"].Columns["CustomerID"],
dataSet.Tables["Orders"].Columns["CustomerID"]);

4) Set the data member for the details table to be the name of relationship that was added to the dataset.
// The name of the relation is to be used as the DataMember for the
// details view
details.DataSource = this.dataSet;

// use the relationship called "CustomersToOrders in the Customers table.


// Remember that we called the relationship "CustomersToOrders".
details.DataMember = "Customers.CustomersToOrders";

5.31 How do I get the row or column that has been clicked on?

You can use the DataGrid's HitTest method, passing it a point in the grid's client coordinate system, and
returning a HitTestInfo object that holds all the row and column information that you want.

[C#]
// X & Y are in the grid' coordinates. If they are in screen coordinates, call dataGrid1.PointToClient method
System.Drawing.Point pt = new Point(X, Y);
DataGrid.HitTestInfo hti = dataGrid1.HitTest(pt);
if(hti.Type == DataGrid.HitTestType.Cell)
{
MessageBox.Show(dataGrid1[hti.Row, hti.Column].ToString());
}
else if(hti.Type == DataGrid.HitTestType.ColumnHeader)
{
MessageBox.Show(((DataView) DataGrid1.DataSource).Table.Columns[hti.Column].ToString());
}

[VB.NET]
' X & Y are in the grid' coordinates. If they are in screen coordinates, call dataGrid1.PointToClient method
Dim pt = New Point(X, Y)
Dim hti As DataGrid.HitTestInfo = dataGrid1.HitTest(pt)
If hti.Type = DataGrid.HitTestType.Cell Then
MessageBox.Show(dataGrid1(hti.Row, hti.Column).ToString())
Else
If hti.Type = DataGrid.HitTestType.ColumnHeader Then 'assumes datasource is a dataview
MessageBox.Show(CType(DataGrid1.DataSource,
DataView).Table.Columns(hti.Column).ToString())
End If
End If

5.32 How do I add an unbound column to my bound datagrid?

The idea is to create the 'bound' table in your dataset, and then add an extra 'unbound' column. The steps are
to derive a custom columnstyle that overrides Paint where you calculate and draw the unbound value. You
can also override Edit to prevent the user from selecting your unbound column. Then to get your datagrid to
use this special column style, you create a tablestyle and add the column styles to it in the order you want
the columns to appear in the datagrid. Here are code snippets that derive the column and use the derived
column. You can download a working sample.

// custom column style that is an unbound column


public class DataGridUnboundColumn : DataGridTextBoxColumn
{
protected override void Edit(System.Windows.Forms.CurrencyManager source, int rowNum,
System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
{
//do not allow the unbound cell to become active
if(this.MappingName == "UnBound")
return;

base.Edit(source, rowNum, bounds, readOnly, instantText, cellIsVisible);


}

protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds,


System.Windows.Forms.CurrencyManager source, int rowNum, System.Drawing.Brush backBrush,
System.Drawing.Brush foreBrush, bool alignToRight)
{

//clear the cell


g.FillRectangle(new SolidBrush(Color.White), bounds);

//compute & draw the value


//string s = string.Format("{0} row", rowNum);
// col 0 + 2 chars from col 1
DataGrid parent = this.DataGridTableStyle.DataGrid;
string s = parent[rowNum, 0].ToString() + ((parent[rowNum, 1].ToString())+ " ").Substring(0,2);
Font font = new Font("Arial", 8.25f);
g.DrawString(s, font, new SolidBrush(Color.Black), bounds.X, bounds.Y);
font.Dispose();

}
}

//code that uses this unbound column


private void Form1_Load(object sender, System.EventArgs e)
{
// Set the connection and sql strings
// assumes your mdb file is in your root
string connString = @"Provider=Microsoft.JET.OLEDB.4.0;data source=C:\northwind.mdb";
string sqlString = "SELECT * FROM customers";

OleDbDataAdapter dataAdapter = null;


DataSet _dataSet = null;

try
{
// Connection object
OleDbConnection connection = new OleDbConnection(connString);

// Create data adapter object


dataAdapter = new OleDbDataAdapter(sqlString, connection);

// Create a dataset object and fill with data using data adapter's Fill method
_dataSet = new DataSet();
dataAdapter.Fill(_dataSet, "customers");
connection.Close();
}
catch(Exception ex)
{
MessageBox.Show("Problem with DB access-\n\n connection: "
+ connString + "\r\n\r\n query: " + sqlString
+ "\r\n\r\n\r\n" + ex.ToString());
this.Close();
return;
}

// Create a table style that will hold the new column style
// that we set and also tie it to our customer's table from our DB
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = "customers";

// since the dataset has things like field name and number of columns,
// we will use those to create new columnstyles for the columns in our DB table
int numCols = _dataSet.Tables["customers"].Columns.Count;

//add an extra column at the end of our customers table


_dataSet.Tables["customers"].Columns.Add("Unbound");

DataGridTextBoxColumn aColumnTextColumn ;
for(int i = 0; i < numCols; ++i)
{
aColumnTextColumn = new DataGridTextBoxColumn();
aColumnTextColumn.HeaderText = _dataSet.Tables["customers"].Columns[i].ColumnName;

aColumnTextColumn.MappingName = _dataSet.Tables["customers"].Columns[i].ColumnName;
tableStyle.GridColumnStyles.Add(aColumnTextColumn);

//display the extra column after column 1.


if( i == 1)
{
DataGridUnboundColumn unboundColStyle = new DataGridUnboundColumn();
unboundColStyle.HeaderText = "UnBound";
unboundColStyle.MappingName = "UnBound";
tableStyle.GridColumnStyles.Add(unboundColStyle); }
}

// make the dataGrid use our new tablestyle and bind it to our table
dataGrid1.TableStyles.Clear();
dataGrid1.TableStyles.Add(tableStyle);
dataGrid1.DataSource = _dataSet.Tables["customers"];

}
}

5.33 How do I get the row and column of the current cell in my datagrid?

You can use the CurrentCell property of the DataGrid.

private void button1_Click(object sender, System.EventArgs e)


{
intcolNum = dataGrid1.CurrentCell.ColumnNumber;
int rowNum = dataGrid1.CurrentCell.RowNumber;
object cellValue = dataGrid1[rowNum, colNum];
string s = string.Format("row={0} col={1} value={2}", rowNum, colNum, cellValue);
MessageBox.Show(s);
}

5.34 How can I prevent the Enter key from moving to the next cell when the user is actively editing the cell
and presses Enter?

Override the method ProcessKeyPreview in your DataGrid.

protected override bool ProcessKeyPreview(ref System.Windows.Forms.Message m)


{
Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;
if((m.Msg == WM_KEYDOWN || m.Msg == WM_KEYUP)
&& keyCode == Keys.Enter )
return false;
return true;
}

5.35 How do I set the width of a column in my DataGrid?

To set a column width, your datagrid must be using a non-null DataGridTableStyle. Once this is in place,
you can set the column width by first getting the tablestyle and then using that object to obtain a column
style with which you can set the width. Here are some code snippets showing how you might do this.
//.... make sure your DataGrid is using a tablestyle
dataGrid1.DataSource = _dataSet.Tables["customers"];
DataGridTableStyle dgts = new DataGridTableStyle();
dgts.MappingName = "customers";
dataGrid1.TableStyles.Add(dgts);

//......

//method to set a column with by colnumber


public void SetColWidth(DataGridTableStyle tableStyle, int colNum, int width)
{
try
{
tableStyle.GridColumnStyles[colNum].Width = width;
tableStyle.DataGrid.Refresh();
}
catch{} //empty catch .. do nothing
}

//....

// here is how you might call this method

private void button1_Click(object sender, System.EventArgs e)


{
DataGridTableStyle tableStyle = dataGrid1.TableStyles["customers"];
SetColWidth(tableStyle, 1, 200);
}

5.36 How can I implement OLE Drag & Drop between a DataGrid and another OLE DnD object that
supports the Text format?

The attached samples (C#, VB) have a derived datagrid that supports OLE D&D with any OLE D&D
provider that handles a Text formatted data object. The derived grid handles six events to allow it to be both
a drop source and a drop target. The sample project has two datagrids where you can drag cell text back and
forth. You can also open Excel, and drag text between Excel and either datagrid.

Here are the events that are handled in this sample.

MouseDown - Used to save the row and column of a mousedown, 'mousedowncell'.


MouseMove - Checks to see if you drag off the mousedowncell, and if so, starts a the DoDragDrop.
MouseUp - Used to reset the mousedowncell.
DragEnter - Checks to see if the data object has text, and if so, allows a Copy operation. (This could
be changed to support Move/Copy.)
DragOver - Used to set a NoDrop cursor if you move over the mousedowncell (if mousedowncell has
been set).
DragDrop - Used to drop the text into the datagrid.
5.37 How can I make my DataGrid support a single select mode, and not the default multiselect mode?

One way to do this is to derive a DataGrid, override its OnMouseDown and OnMouseMove methods. In
the OnMouseDown, handle selecting and unselecting in your code without calling the base class if the click
is on the header. In the OnMouseMove, don't call the baseclass to avoid dragging selections. Below is a
code snippet for a sample derived DataGrid. You can download a full project (C#, VB).

public class MyDataGrid : DataGrid


{
private int oldSelectedRow = -1;

protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)


{
//don't call the base class if left mouse down
if(e.Button != MouseButtons.Left)
base.OnMouseMove(e);
}

protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)


{
//don't call the base class if in header
DataGrid.HitTestInfo hti = this.HitTest(new Point(e.X, e.Y));
if(hti.Type == DataGrid.HitTestType.Cell)
{
if(oldSelectedRow > -1)
this.UnSelect(oldSelectedRow);
oldSelectedRow = -1;
base.OnMouseDown(e);
}
else if(hti.Type == DataGrid.HitTestType.RowHeader)
{
if(oldSelectedRow > -1)
this.UnSelect(oldSelectedRow);
if((Control.ModifierKeys & Keys.Shift) == 0)
base.OnMouseDown(e);
else
this.CurrentCell = new DataGridCell(hti.Row, hti.Column);
this.Select(hti.Row);
oldSelectedRow = hti.Row;
}
}
}

5.38 How can I get celltips or tooltips to vary from cell to cell in my DataGrid?
One way to do this is to use a ToolTip control and reset the control text as the mouse moves from cell to
cell. Below is a derived DataGrid class that implements this idea. The main points are:

• Have members that track the current hitRow and hitCol where the mouse is.
• In a MouseMove handler, do a HitTest on the mouse location to see if there is a new hit cell. If so,
set the hitRow & hitCol, and hook the tooltip to hold your text according to the cell. In our sample,
we just display the string value of the grid cell.
• Finally, in the MouseMove handler, after setting a new text in the tooltip, set the tooltip active so it
can show itself in due time.

public class DataGridCellTips : DataGrid


{
private int hitRow;
private int hitCol;
private System.Windows.Forms.ToolTip toolTip1;

public DataGridCellTips()
{
hitRow = -1;
hitCol = -1;
this.toolTip1 = new System.Windows.Forms.ToolTip();
this.toolTip1.InitialDelay = 1000;
this.MouseMove += new MouseEventHandler(HandleMouseMove);
}

private void HandleMouseMove(object sender, MouseEventArgs e)


{
DataGrid.HitTestInfo hti = this.HitTest(new Point(e.X, e.Y));
if(hti.Type == DataGrid.HitTestType.Cell
&& ( hti.Row != hitRow || hti.Column != hitCol) )
{ //new hit row
hitRow = hti.Row;
hitCol = hti.Column;
if(this.toolTip1 != null && this.toolTip1.Active)
this.toolTip1.Active = false; //turn it off
this.toolTip1.SetToolTip(this, this[hitRow, hitCol].ToString());
this.toolTip1.Active = true; //make it active so it can show itself
//Console.WriteLine("MouseMove "+ hitRow.ToString() + " " + hitCol.ToString());
}
}
}

5.39 How can I get notification of the changing of a value in a column of comboboxes within my datagrid?
This solution is based off the combobox for datagrid columns found in this FAQ. That solution replaces the
standard textbox with a combobox. To get notifications of the changes, a delegate is passed into the
constructor for the custom column style. This delegate is called anytime the combobox value changes. It
passes the row number and value as arguments. You can download sample code (C#, VB) that shows the
implementation.

5.40 How can I make the datagrid have no currentcell?

There appears to be no method to turn off a currentcell. When a cell is being edited, it is the TextBox
embedded in the columnstyle that has the focus, and is displaying the highlighted text. You will notice in
this situation, if you click the grid's title bar above the column headers, this TextEdit control loses focus,
and the datagrid appears to have no current cell.

We can simulate this click from code, and use it to expose a method in our datagrid to SetNoCurrentCell.
Below is some code to illustrate this idea.

public class MyDataGrid : DataGrid


{
public const int WM_LBUTTONDOWN = 513; // 0x0201
public const int WM_LBUTTONUP = 514; // 0x0202

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool SendMessage(IntPtr hWnd, Int32 msg, Int32 wParam, Int32
lParam);

public void SetNoCurrentCell()


{
//click on top left corner of the grid
SendMessage( this.Handle, WM_LBUTTONDOWN, 0, 0);
SendMessage( this.Handle, WM_LBUTTONUP, 0, 0);
}
}

Here is some VB code.

Public Class MyDataGrid


Inherits DataGrid

Public WM_LBUTTONDOWN As Integer = 513


Public WM_LBUTTONUP As Integer = 514

Shared _
Function SendMessage(hWnd As IntPtr, msg As Int32, wParam As Int32, lParam As Int32) As Boolean

Public Sub SetNoCurrentCell()


'click on top left corner of the grid
SendMessage(Me.Handle, WM_LBUTTONDOWN, 0, 0)
SendMessage(Me.Handle, WM_LBUTTONUP, 0, 0)
End Sub 'SetNoCurrentCell
End Class 'MyDataGrid

5.41 How can I make my grid never have an active edit cell and always select whole rows (as in a browser-
type grid)?

For a single row select datagrid, you can get both these behaviors by using a custom column style and
overriding its Edit method. In your override, handle unselecting and selecting the current row, and DO
NOT call the base class. Not calling the base class keeps the cell from becoming active. Here is a code
snippet suggesting how this might be done. You can download a full working project (CS, VB).

public class DataGridNoActiveCellColumn : DataGridTextBoxColumn


{
private int SelectedRow = -1;
protected override void Edit(System.Windows.Forms.CurrencyManager source, int rowNum,
System.Drawing.Rectangle bounds, bool readOnly,stringi nstantText,bool cellIsVisible)
{
//make sure previous selection is valid
if(SelectedRow > -1 && SelectedRow < source.List.Count + 1)
this.DataGridTableStyle.DataGrid.UnSelect(SelectedRow);
SelectedRow = rowNum;
this.DataGridTableStyle.DataGrid.Select(SelectedRow);
}
}

If you want to handle multi-selections, then there is more work to be done. One solution is to still override
Edit as above, but have an empty implementation. Do not have the code the handles the selected row and
do not call the baseclass. To handle the selections in this case, subclass the datagrid and override its
OnMouseDown virtual method to change all cell clicks into row header clicks. Also override
OnCurrentCellChanged to handle moving the current cell with the keyboard. You can download a sample
(C#, VB) that implements this functionality.

5.42 I have hidden (column width = 0) columns on the right side of my datagrid, but tabbing does not work
properly. How can I get tabbing to work?

As you tabbed to the right side of your grid, you have to tabbed through these zero width column and that is
causing the tab key to appear not to work properly. One solution is to handle the grid's CurrentCellChanged
event, and if you are on a border cell (among the hidden columns), then explicitly set the proper currentcell.

//columns 3-6 are hidden with 0-column width...


private int LEFTHIDDENCOLUMN = 3;
private int RIGHTHIDDENCOLUMN = 6;

private void dataGrid1_CurrentCellChanged(object sender, System.EventArgs e)


{
if(dataGrid1.CurrentCell.ColumnNumber == LEFTHIDDENCOLUMN)
dataGrid1.CurrentCell = new DataGridCell(dataGrid1.CurrentCell.RowNumber + 1, 0);
else if(dataGrid1.CurrentCell.ColumnNumber == RIGHTHIDDENCOLUMN)
dataGrid1.CurrentCell = new DataGridCell(dataGrid1.CurrentCell.RowNumber,
LEFTHIDDENCOLUMN - 1);
}

5.43 How can I get the number of rows in my DataGrid?

One way you can do this is through the BindingManager.Count property.

[C#]
int numRows = dataGridDetails.BindingContext[dataGridDetails.DataSource,
dataGridDetails.DataMember].Count;

[VB.NET]
Dim numRows as Integer = i dataGridDetails.BindingContext(dataGridDetails.DataSource,
dataGridDetails.DataMember).Count;

5.44 How do I format a date column in a datagrid?

If you have added a table style to your datagrid (so individual column styles have been generated), then you
can use code such as this to set the Format property of the particular column style.

[C#]
//add format col 3 columnstyle where column 3 holds a date...

DataGridTextBoxColumn dgtbc;
dgtbc = dataGrid1.TableStyles[0].GridColumnStyles[3] as DataGridTextBoxColumn;

if(dgtbc != null)
dgtbc.Format = "g"; // or "u" or whatever format you want to see

[VB.NET]
'add format col 3 columnstyle where column 3 holds a date...

Dim dgtbc as DataGridTextBoxColumn


dgtbc = CType(dataGrid1.TableStyles(0).GridColumnStyles(3), DataGridTextBoxColumn)

If Not dgtbc is Nothing Then


dgtbc.Format = "g" ' or "u" or whatever format you want to see
End If
5.45 How can I change the width of the row headers or hide them?

You can get at the width and visibility of the header row/column through a DataGridTableStyle.
DataGridTableStyle has properties such as RowHeadersVisible and RowHeadersWidth.
DataGridTableStyle also controls things like selections colors and GridLine styles.

// Create a table style that will hold the new column style
// that we set and also tie it to our customer's table from our DB
DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = "customers";

//hide the column headers


tableStyle.ColumnHeadersVisible = false;

//change width of the row headers


tableStyle.RowHeadersWidth = 100;

// make the dataGrid use our new tablestyle and bind it to our table
dataGrid1.TableStyles.Clear();

dataGrid1.TableStyles.Add(tableStyle);

5.46 How do I catch a doubleclick in my datagrid?

The problem is that the first click of a double click may be caught by the datagrid (and used to activate the
cell) while the second click goes to the TextBox for the columnstyle object. This means the TextBox thinks
this is a singleclick, and does not fire its doubleclick event. One solution is to mark the time of the click
caught by the datagrid. Then look at this time in the TextBox's mousedown handler to see if in fact the
single click being looked at by the TextBox is part of a double click. You can download a sample (C#, VB)
that illustrates how this might be done.

5.47 How can I make my last column wide enough to exactly occupy all the client area of the datagrid?

If you have added a TableStyle for your grid, then the code below should set the right column width to be
the empty space from a button click. If you need to dynamically do this in response to the user sizing other
columns, then there may be more work. But if you only need to do it at the end of your Form_Load, then
this code might be sufficient. It assumes your datasource is a datatable. You can download a sample project
(C#, VB).

private void button1_Click(object sender, System.EventArgs e)


{
int numCols = ((DataTable)(dataGrid1.DataSource)).Columns.Count;

//the fudge -4 is for the grid borders


int targetWidth = dataGrid1.ClientSize.Width - SystemInformation.VerticalScrollBarWidth - 4;

int runningWidthUsed = this.dataGrid1.TableStyles["customers"].RowHeaderWidth;

for(int i = 0; i < numCols - 1; ++i)


runningWidthUsed += this.dataGrid1.TableStyles["customers"].GridColumnStyles[i].Width;

if(runningWidthUsed < targetWidth)


this.dataGrid1.TableStyles["customers"].GridColumnStyles[numCols - 1].Width = targetWidth -
runningWidthUsed;
}

5.48 How can I prevent my user from sizing columns in my datagrid?

You can do this by subclassing your grid and overriding OnMouseMove, and not calling the baseclass if the
point is on the columnsizing border.

[C#]
public class MyDataGrid : DataGrid
{
protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
{
DataGrid.HitTestInfo hti = this.HitTest(new Point(e.X, e.Y));
if(hti.Type == DataGrid.HitTestType.ColumnResize)
{
return; //no baseclass call
}
base.OnMouseMove(e);
}
}

[VB.NET]
Public Class MyDataGrid
Inherits DataGrid
Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
Dim hti As DataGrid.HitTestInfo = Me.HitTest(New Point(e.X,e.Y))
If hti.Type = DataGrid.HitTestType.ColumnResize Then
Return 'no baseclass call
End If
MyBase.OnMouseMove(e)
End Sub
End Class

The above code prevents the sizing cursor from appearing, but as Stephen Muecke pointed out to us, if the
user just clicks on the border, he can still size the column. Stephen's solution to this problem is to add
similar code in an override of OnMouseDown.
[C#]
protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
{
DataGrid.HitTestInfo hti = this.HitTest(new Point(e.X, e.Y));
if(hti.Type == DataGrid.HitTestType.ColumnResize)
{
return; //no baseclass call
}
base.OnMouseDown(e);
}

[VB.NET]
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
Dim hti As DataGrid.HitTestInfo = Me.HitTest(New Point(e.X,e.Y))
If hti.Type = DataGrid.HitTestType.ColumnResize Then
Return 'no baseclass call
End If
MyBase.OnMouseDown(e)
End Sub

5.49 How can I catch the bool values changing in a DataGridBoolColumn?

There is no event fired when the boolean value changes. In the attached sample (C#, VB), a
BoolValueChanged event has been added to a columnstyle derived from DataGridBoolColumn. Catching
the changes requires some effort. The strategy is to save the current value when the cell begins being
edited. This is done in an override of Edit. Then in a Paint override, checks are done to see if there is a click
in the checkbox cell or if the space bar is hit. If either of these situations happen when the cell is actively
being edited, the bool value is changed and the event fired.

5.50 When I click on a row header, the row is selected and no cell is active. How can I do this
programmatically?

This code adds a method to a derived grid that simulates a mouseclick on the rowheader of the row passed
into the method.

public class MyDataGrid : DataGrid


{

public const int WM_LBUTTONDOWN = 513; // 0x0201


public const int WM_LBUTTONUP = 514; // 0x0202

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool SendMessage(IntPtr hWnd, Int32 msg, Int32 wParam, Int32 lParam);

public void ClickRowHeader(int row)


{
//get a point to click
Rectangle rect = this.GetCellBounds(row, 0);
Int32 lparam = MakeLong(rect.Left - 4, rect.Top + 4);

//clickit
SendMessage( this.Handle, WM_LBUTTONDOWN, 0, lparam);
SendMessage( this.Handle, WM_LBUTTONUP, 0, lparam);
}

static int MakeLong(int LoWord, int HiWord)


{
return (HiWord << 16) | (LoWord & 0xffff);
}

}
.....
.....
//usage - myDataGrid is of type MyDataGrid.
private void button2_Click(object sender, System.EventArgs e)
{
myDataGrid.ClickRowHeader(2);
}

5.51 How can I force the vertical scrollbar in my DataGrid to always be visible?

Derive a DataGrid. In your derived grid, add a handler for the VertScrollBar.VisibleChanged event. In your
handler, if the scrollbar is not visible, size it and position it, and then show it. The code below assumes no
horizontal scrollbar is necessary. If it is present, you would have to adjust the sizing code.

C#
public class MyDataGrid : DataGrid
{

public MyDataGrid()
{
//make scrollbar visible & hook up handler
this.VertScrollBar.Visible = true;
this.VertScrollBar.VisibleChanged += new EventHandler(ShowScrollBars);
}

private int CAPTIONHEIGHT = 21;


private int BORDERWIDTH = 2;

private void ShowScrollBars(object sender, EventArgs e)


{
if(!this.VertScrollBar.Visible)
{
int width = this.VertScrollBar.Width;
this.VertScrollBar.Location = new Point(this.ClientRectangle.Width - width - BORDERWIDTH,
CAPTIONHEIGHT);
this.VertScrollBar.Size = new Size(width, this.ClientRectangle.Height - CAPTIONHEIGHT -
BORDERWIDTH);
this.VertScrollBar.Show();
}
}
}

VB.NET
Public Class MyDataGrid
Inherits DataGrid

Public Sub New()


'make scrollbar visible & hook up handler
Me.VertScrollBar.Visible = True
AddHandler Me.VertScrollBar.VisibleChanged, AddressOf ShowScrollBars
End Sub 'New

Private CAPTIONHEIGHT As Integer = 21


Private BORDERWIDTH As Integer = 2

Private Sub ShowScrollBars(sender As Object, e As EventArgs)


If Not Me.VertScrollBar.Visible Then
Dim width As Integer = Me.VertScrollBar.Width
Me.VertScrollBar.Location = New Point(Me.ClientRectangle.Width - width - BORDERWIDTH,
CAPTIONHEIGHT)
Me.VertScrollBar.Size = New Size(width, Me.ClientRectangle.Height - CAPTIONHEIGHT -
BORDERWIDTH)
Me.VertScrollBar.Show()
End If
End Sub 'ShowScrollBars
End Class 'MyDataGrid

5.52 How can I autosize a column in my datagrid?

One way to do this is to use MeasureString to compute the size of the text in each cell, and then take the
maximum value. Below is a code snippet that does this. It assumes your datagrid is bound to a datatable.
You can download a full working sample. (C#,VB).

public void AutoSizeCol(int col)


{
float width = 0;
int numRows = ((DataTable) dataGrid1.DataSource).Rows.Count;

Graphics g = Graphics.FromHwnd(dataGrid1.Handle);
StringFormat sf = new StringFormat(StringFormat.GenericTypographic);
SizeF size;
for(int i = 0; i < numRows; ++ i)
{
size = g.MeasureString(dataGrid1[i, col].ToString(), dataGrid1.Font, 500, sf);
if(size.Width > width)
width = size.Width;
}

g.Dispose();

dataGrid1.TableStyles["customers"].GridColumnStyles[col].Width = (int) width + 8; // 8 is for leading


and trailing padding
}

5.53 How can I get rid of the error icon that appears when there is an editing error?

Adam Chester gives this solution in a posting on the microsoft.public.dotnet.framework.windowsforms


newgroup.

DataTable dt = (DataTable)dataGrid1.DataSource;
foreach(DataRow row in dt.GetErrors())
{
row.RowError = "";
foreach(DataColumn col in dt.Columns)
row.SetColumnError(col, "");
}

5.54 How do I find the top-left visible cell in a datagrid?

In a Windows Forms DataGrid, there is no property exposed that gives you this information. But here is
little trick that will allow you to get the top-left visible cell.

1) Add a private member Point pointInCell00 to the form containing the datagrid.

2) After the datagrid has been initialized, but before your user has been able to scroll it (say at the end of
the Form_Load event), use code such as this to initialize pointInCell00 to be a point in cell 0,0.

pointInCell00 = new Point(dataGrid1.GetCellBounds(0,0).X + 4, dataGrid1.GetCellBounds(0,0).Y + 4);

3) Then add this method to return DataGridCell that is the top-left cell.

public DataGridCell TopLeftVisibleCell()


{
DataGrid.HitTestInfo hti = dataGrid1.HitTest(this.pointInCell00);
return new DataGridCell(hti.Row, hti.Column);
}

//sample usage...
private void button1_Click(object sender, System.EventArgs e)
{
DataGridCell dgc = TopLeftVisibleCell();

MessageBox.Show(dgc.RowNumber.ToString() + " " + dgc.ColumnNumber.ToString());


}

5.55 I want to display negative values with a CR suffix, instead of a minus sign. How can I perform custom
formatting on the cells in my datagrid?

Take a look at this Microsoft KB article, HOW TO: Extend the Windows Form DataGridTextBoxColumn
Control to Custom-Format Data (Q318581). It subclasses a DataGridColumnStyle and overrides both
GetColumnValueAtRow and Commit to implement this behavior.

5.56 I want to do sort of a database join of two tables. How can I use data from two DataTables in a single
DataGrid?

Take a look at this Microsoft KB article, HOW TO: Extend the Windows Form DataGridTextBoxColumn
to Display Data From Other Tables (C#,VB). It subclasses a DataGridColumnStyle and overrides
GetColumnValueAtRow, Commit and ReadOnly to implement this behavior.

5.57 How do I display a column of buttons such as pushbuttons or combobox buttons?

This sample (download C#, download VB) derives two custom columnstyles that display buttons. One
displays a pushbutton with the cell text used as the button label. The second columnstyle displays text plus
a dropdown button similar to a combobox button. Both columnstyles have an event that your form can
handle to respond to clicks on the buttons. The row and column of the click are passed as part of the event
arguments.

Both columnstyles derive from DataGridTextBoxColumn, and override Paint and Edit. The Edit override
does not call the baseclass to avoid allowing the cell going into the edit mode. In the Paint override, the text
is drawn, and a bitmap showing the button face is drawn.

There is no mouse handling within a columnstyle. To catch the click action, the columnstyle must handle
the datagrid's MouseDown and MouseUp events. In the columnstyle handlers for these events, the handler
draws the depressed button as well as firing the columnstyle's ColumnButtonClick event.

Your handler for this ColumnButtonClick event should take whatever action as a result of the buttonclick.
In the sample projects, the handler just displays a messagebox.
5.58 How can I put up a confirmation question when the user tries to delete a row in the datagrid by
clicking on the row header and pressing the Delete key?

You can handle this by subclassing your grid and overriding either PreProcessMessage or
ProcessDialogKey. The code below assumes your datasource is a dataview. If it is not, you could just
remove that check

[C#]
public override bool PreProcessMessage( ref Message msg )
{
Keys keyCode = (Keys)(int)msg.WParam & Keys.KeyCode;
if(msg.Msg == WM_KEYDOWN
&& keyCode == Keys.Delete
&& ((DataView) this.DataSource).AllowDelete)
{
if(MessageBox.Show("Delete this row?", "", MessageBoxButtons.YesNo) == DialogResult.No)
return true;
}
return base.PreProcessMessage(ref msg);
}

[VB.NET] (courtesy of Erik Johansen)


Public Class DataGrid_Custom
Inherits DataGrid

Private Const WM_KEYDOWN = &H100

Public Overrides Function PreProcessMessage(ByRef msg As System.Windows.Forms.Message) As


Boolean

Dim keyCode As Keys = CType((msg.WParam.ToInt32 And Keys.KeyCode), Keys)


If msg.Msg = WM_KEYDOWN And keyCode = Keys.Delete Then
If MessageBox.Show("Delete This Row?", "Confirm Delete", MessageBoxButtons.YesNo) =
DialogResult.No Then
Return True
End If
End If
Return MyBase.PreProcessMessage(msg)

End Function
End Class

5.59 How can I enable column selections in my datagrid?

Here is a sample (C#, VB) that has column selections implemented. It derives a datagrid, adds a columns
selection array list, and maintains this list in an override of OnMouseDown. Then to handle actually
drawing the selected columns, it uses a derived column style, and sets the backBrush color and foreBrush
color to the selection values in the override of the Paint method when it needs to draw a selected cell.

As an alternative to drawing the selection in a derived column style, you could just draw the selection in
your derived grid by overriding OnPaint, calling the base class and then looping through the columns
selections, filling a rectangle over the selected columns. The problem with this technique is that you would
either have to redraw text in column with the correct forecolor, or you would have to use an alphablended
color to let the text show through the selection rectangle. Using an alphablended color would eliminate the
need to a column style override, but would give a different appearance than the 'standard' selections that
you see in a datagrid. The sample allows the row selections to continue to work so the column style
override makes sense here.

5.60 How do I programmatically scroll the datagrid to a particular row?

The DataGrid has a protected GridVScrolled member that can be used to scroll the grid. To use it, you can
derive from DataGrid and add a ScrollToRow method. Here is a code snippet.

Public Class MyDataGrid


Inherits DataGrid
Sub ScrollToRow(ByVal row As Integer)
If Not Me.DataSource Is Nothing Then
Me.GridVScrolled(Me, New ScrollEventArgs(ScrollEventType.LargeIncrement, row))
End If
End Sub
End Class

This solution uses information provided by Daniel Herling (MS) in the


microsoft.public.dotnet.framework.windowsforms.databinding newsgroup.

5.61 How can I place text in the rowheader column of my datagrid?

There is no text property exposed for a rowheader cell. But you can handle the Paint event and draw header
text yourself. You can download sample projects (C#, VB) that illustrate one technique for doing so.

The sample loads the datagrid in the form's Load event. In addition, this event is used to set the
rowheaderwidth of the datagrid, and to remember the point where cell 0,0 is located. This point will allow
us to find the toprow number when we need it to start drawing the header text. A handler for the datagrid's
Paint event is used to draw the text. It finds the toprow using the point from the original cell 0,0, and using
the toprow determines the correct text for each rowheader. Finally, to avoid the complication of the user
changing rowheights, we derive a new grid to prevent this.

private void dataGrid1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)


{
int row = TopRow();
int yDelta = dataGrid1.GetCellBounds(row, 0).Height + 1;
int y = dataGrid1.GetCellBounds(row, 0).Top + 2;
CurrencyManager cm = (CurrencyManager) this.BindingContext[dataGrid1.DataSource,
dataGrid1.DataMember];
while(y < dataGrid1.Height - yDelta && row < cm.Count)
{
//get & draw the header text...
string text = string.Format("row{0}", row);
e.Graphics.DrawString(text, dataGrid1.Font, new SolidBrush(Color.Black), 12, y);
y += yDelta;
row++;
}
}

Here is a datagrid with red row headers containing text.

5.62 How do I set default values for new rows in my datagrid?

You use the DataColumn.DefaultValue property to provide default values for new rows. You access this
property through the DataTable associated with the DataGrid,

[C#]
this.dataGrid1.DataSource = this._dataSet.Tables["orders"];
....
....
this._dataSet.Tables["Orders"].Columns[1].DefaultValue = "CustID"; // default value for column 1
this._dataSet.Tables["Orders"].Columns["OrderDate"].DefaultValue = DateTime.Now; // default value
for OrderDate column

[VB.NET]
Me.dataGrid1.DataSource = Me._dataSet.Tables("Orders")
....
....
Me._dataSet.Tables("Orders").Columns(1).DefaultValue = "CustID" ' default value for column 1
Me._dataSet.Tables("Orders").Columns("OrderDate").DefaultValue = DateTime.Now ' default value for
OrderDate column

5.63 How do I iterate through all the rows and columns in my datagrid?

You use the row index and column index as indexers on the DataGrid object.

[C#]
private void button1_Click(object sender, System.EventArgs e)
{
CurrencyManager cm = (CurrencyManager)this.BindingContext[this.dataGrid1.DataSource];

int rowCount = cm.Count;


//assumes datasource is a datatable...
int colCount = ((DataTable)this.dataGrid1.DataSource).Columns.Count;

for(int row = 0; row < rowCount; row++)


{
for(int col = 0; col < colCount; col++)
{
object cellValue = this.dataGrid1[row, col];
Console.Write(cellValue.ToString() + " ");
}
Console.WriteLine("");
}
}

[VB.NET]
Private Sub button1_Click(sender As Object, e As System.EventArgs)
Dim cm As CurrencyManager = CType(Me.BindingContext(Me.dataGrid1.DataSource),
CurrencyManager)

Dim rowCount As Integer = cm.Count


'assumes datasource is a datatable...
Dim colCount As Integer = CType(Me.dataGrid1.DataSource, DataTable).Columns.Count

Dim row As Integer


For row = 0 To rowCount - 1
Dim col As Integer
For col = 0 To colCount - 1
Dim cellValue As Object = Me.dataGrid1(row, col)
Console.Write((cellValue.ToString() + " "))
Next col
Console.WriteLine("")
Next row
End Sub 'button1_Click

5.64 How can I specially color only the currentcell of my readonly datagrid?

You can use the first technique listed in this FAQ: How do I color an individual cell depending upon its
value or some external method?

The idea is to derive a custom columnstyle. override its Paint method to specially color the background of
the currentcell. Also, override the Edit to avoid the current cell becoming active. Below is a code snippet
showing how you can do this. You can also download samples(C#, VB).

Public Class DataGridColoredTextBoxColumn


Inherits DataGridTextBoxColumn

Private column As Integer ' column where this columnstyle is located...


Public Sub New()
column = -2
End Sub

Protected Overloads Overrides Sub Paint(ByVal g As Graphics, ByVal bounds As Rectangle, ByVal
source As CurrencyManager, ByVal rowNum As Integer, ByVal backBrush As Brush, ByVal foreBrush As
Brush, ByVal alignToRight As Boolean)

Try
Dim grid As DataGrid = Me.DataGridTableStyle.DataGrid

'first time set the column properly


If column = -2 Then
Dim i As Integer
i = Me.DataGridTableStyle.GridColumnStyles.IndexOf(Me)
If i > -1 Then
column = i
End If
End If

If grid.CurrentRowIndex = rowNum And grid.CurrentCell.ColumnNumber = column Then


backBrush = New LinearGradientBrush(bounds, Color.FromArgb(255, 200, 200),
Color.FromArgb(128, 20, 20), LinearGradientMode.BackwardDiagonal)
foreBrush = New SolidBrush(Color.White)
End If
Catch ex As Exception
' empty catch
Finally
' make sure the base class gets called to do the drawing with
' the possibly changed brushes
MyBase.Paint(g, bounds, source, rowNum, backBrush, foreBrush, alignToRight)
End Try

End Sub

Protected Overloads Overrides Sub Edit(ByVal source As System.Windows.Forms.CurrencyManager,


ByVal rowNum As Integer, ByVal bounds As System.Drawing.Rectangle, ByVal [readOnly] As Boolean,
ByVal instantText As String, ByVal cellIsVisible As Boolean)
'do nothiing... don't call the basecalss
End Sub
End Class

5.65 How can I make the Enter Key behave like the Tab Key and move to the next cell?
You can override ProcessCmdKey, catch the Enter Key, and swap it for a Tab key by sending a Tab, and not
processing the Enter Key.

[C#]
public class MyDataGrid : DataGrid
{
protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg,
System.Windows.Forms.Keys keyData)
{
if(msg.WParam.ToInt32() == (int) Keys.Enter)
{
SendKeys.Send("{Tab}");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}

[VB.NET]
Public Class MyDataGrid
Inherits DataGrid

Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message,


keyData As System.Windows.Forms.Keys) As Boolean
If msg.WParam.ToInt32() = CInt(Keys.Enter) Then
SendKeys.Send("{Tab}")
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function 'ProcessCmdKey

End Class 'MyDataGrid

5.66 How do I use the DataColumn.Expression property to add a computed/combined column to my


datagrid?

The idea is to load your datatable in a normal fashion. Once the datatable is loaded, you can add an
additional column that is computed from the other columns in your datatable. In the sample(CS, VB), we
load the CustomerID, CompanyName, ContactName and ContactTitle from the Customers table in the
NorthWind database. We then add an additional column that concatenates the ContactName and
ContactTitle into one column.

To add the additional column, we create a DataColumn, set a mapping name, and then use the Expression
property to define how the column is to be computed.
[C#]
DataColumn dc = new DataColumn("Contact", typeof(string));
dc.Expression = "ContactName + ':' +ContactTitle";
_dataSet.Tables["customers"].Columns.Add(dc);

[VB.NET]
Dim dc As DataColumn
dc = New DataColumn("Contact", GetType(System.String))
dc.Expression = "ContactName + ':' +ContactTitle"
_dataSet.Tables("customers").Columns.Add(dc)

The sample actually shows two datagrids. The first one uses the default binding to display the entire table
including our added column. In the second datagrid, we add a custom DataGridTableStyle to only display
the CustomerID, CompanyName and our added column.

5.67 How can I change the font used in a grid cell on a cell by cell or row by row basis?

One way to do this is to use a derived columnstyle, override the Paint method and do the text drawing
yourself, using whatever font or colors you like. If you add an event to your derived column style that is
fired immediately before the text is drawn, and use the event args to get the font and color information, you
can let the event handler completely determine the look of any cell.

The attached samples (C#, VB) use this technique to create a grid that looks like the grid in the picture.
Both color and font varies on a cell basis or row basis in this picture.

5.68 How can I use a mouse to select cell ranges in my datagrid?

The Windows Forms DataGrid does not support the selection of a range of cells other than a group of rows.
To select a row, you can click on its row header. But if you want to select a rectangular group of cells, you
cannot.

To add this support, you can catch the mousedown on a cell, and in mousemove, track whether the mouse is
dragged with the button down to other cells. If so, draw a selection rectangle over this group of cells. The
attached samples (C#, VB) show how this might be done. The drawing of the selection rectangle is done in
an OnPaint override. The samples also try to handle autoscrolling as you hit a grid border so the selection
process can continue for cells that are not currently visible. To make the selection rectangle look nicer, the
code also hides the current cell when it draws a selection rectangle.

The samples have a derived DataGrid that has a public member, SelectedRange, that holds the TopLeft and
BottomRight coordinates of the selected range. The derived grid also has a public event,
SelectionChanging, that fires prior to the selection changing as you drag your mouse. The event passes both
the old selection and the new selection, and allows you to cancel the action if you choose.

5.69 How can I control the cursor over my DataGrid?


One way you can do this is to derive the DataGrid and override its WndProc method to handle the
WM_SETCURSOR method yourself. In your override, you can do hit testing to decide when you want to
set the cursor, or when you want to call the base class and let it set the cursor. Here are sample projects (VB
and C#) showing the technique.

Public Class MyDataGrid


Inherits DataGrid
Private Const WM_SETCURSOR As Integer = 32

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)


If m.Msg <> WM_SETCURSOR Then
MyBase.WndProc(m)
Else
'see if you want the cursor - in col 1, rows 2, 3, 4
Dim pt As Point = Me.PointToClient(Control.MousePosition)
Dim hti As DataGrid.HitTestInfo = Me.HitTest(pt.X, pt.Y)
If hti.Column = 1 AndAlso hti.Row > 1 AndAlso hti.Row < 5 Then
Cursor.Current = Cursors.Hand
'if not, call the baseclass
Else
MyBase.WndProc(m)
End If
End If
End Sub 'WndProc

Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)


If Cursor.Current.Equals(Cursors.Hand) Then
MessageBox.Show("My MouseDown")
Else
MyBase.OnClick(e)
End If
End Sub 'OnMouseDown
End Class 'MyDataGrid

5.70 How can I programatically add and remove columns in my DataGrid without modifying the DataTable
datasource?

You can control the columns displayed in the DataGrid through the
DataGrid.TableStyle[0].GridColumnStyles collection. To do so, create a DataGridTableStyle and set its
MappingName property to point to the name of your DataTable which is the DataSource for the DataGrid.
Next, add this DataGridTableStyle to the DataGrid.TableStyles property. Finally, set the
DataGrid.DataSource property to the DataTable. Doing things in this order, guarantees that the
DataGridTableStyle.GridColumnStyles collection will be fully populated showing all the DataTable
columns in the the DataGrid.

Then to add and remove columns from the DataGrid, you only have to add and remove
DataGridColumnStyle objects from this DataGrid.TableStyle[0].GridColumnStyles collection. Removing
them is straight-forward through a Remove method call. But inserting them requires more work as there is
no InsertAt method defined for this collection. To handle this problem, you can create a new array of
DataGridColumnStyles, and populate this array in the necessary order to reflect the DataGrid with an
inserted column. Then you can clear the old collection, and create a new collection with this new array. You
really are not creating all new DataGridColumnStyle objects, but are simply reordering the existing ones in
a new collection.

Here is a sample project containing both C# and VB.NET code showing how you might do this.

5.71 How can I have a column of bitmaps in a DataGrid?

You can derive a custom columnstyle and override its Paint method to draw the image. Here are both C#
and VB.Net samples.

The Paint override offers three ways to draw the bimap in the cell; size it to fit the cell bounds, size it
proportionally to fit the cell bounds, and draw it with it's original size (clipping the bitmap to fit in the cell
bounds). In the sample, the DataGrid is anchored on all four sides, so as you size the form, the DataGrid
sizes as well. The dataGrid1_Resized event is handled to dynamically change the PreferredRowHeight and
PreferredColumnWidth so the cells occupy all of the datagrid's client area. So, as you size the form, the
grid cells size also so you can easily see the bitmaps.

5.72 How can I add my custom columnstyles to the designer so I can use them in my DataGrid at design
time?

To use custom columnstyles in the designer, you need to do three things.

1) Derive a CustomColumnStyle to implement the functionality you want.


2) Derive a DataGridTableStyle class and add a new GridColumnStyles property that uses this derived
CollectionEditor. This GridColumnStyle hides the baseclass member.
3) Derive a DataGrid and add a new TableStyles collection that uses your derived tablestyle.

Both steps 2 and 3 will require you to derive a CollectionEditor and override CreateNewItemTypes to use
the derived classes from each step in the designer.

Here is a sample project showing how you might do these things.

5.73 After scrolling with the mouse wheel on a selected row in a DataGrid I cannot get it back into view. Is
there a work around?

When you select a row in the DataGrid and scroll it out of view using the mouse wheel, you cannot get it
back into view. The following is a workaround posted by one Windows Forms User:

[C#]
this.dataGrid1.MouseWheel+=new MouseEventHandler(dataGrid1_MouseWheel);
private void dataGrid1_MouseWheel(object sender, MouseEventArgs e)
{
this.dataGrid1.Select();

[VB.NET]
AddHandler Me.dataGrid1.MouseWheel, addressof dataGrid1_MouseWheel

Private Sub dataGrid1_MouseWheel(ByVal sender As Object, ByVal e As MouseEventArgs)


Me.dataGrid1.Select()

End Sub

5.74 How can I make the DataGrid column be blank and not display (null) as the default value?

When you go to a new row in a DataGrid, the columns display (null). To prevent this behavior and make all
the columns be empty, you can set the DefaultValue property of the DataColumn to be String.Empty.

5.75 How can I add a DateTimePicker column style to the DataGrid?

This MSDN reference shows how how to create DateTimePicker column style in the DataGrid.

5.76 How do I determine the DataGridTableStyle MappingName that should used for a DataGrid to make
sure the grid uses my tablestyle?

The DataGrid looks for a DataGridTableStyle.MappingName that is the type name of its datasource. So,
depending upon what datasource you are using, this may be "ArrayList" for a ArrayList, "MyCollection[]"
for an array of MyCollection objects, or "MyTableName" for a datatable, or whatever.

Here is a code snippet provide by NoiseEHC on the


microsoft.public.dotnet.framework.windowsforms.controls newsgroup that you can use to see exactly what
mappingname is required for your datasource.

[C#]
//usage
ShowMappingName(dataGrid1.DataSource);

//implementation
void ShowMappingName(object src)
{
IList list = null;
Type type = null;
if(src is Array)
{
type = src.GetType();
list = src as IList;
}
else
{
if(src is IListSource)
src = (src as IListSource).GetList();
if(src is IList)
{
type = src.GetType();
list = src as IList;
}
else
{
MessageBox.Show("error");
return;
}
}
if(list is ITypedList)
MessageBox.Show((list as ITypedList).GetListName(null));
else
MessageBox.Show(type.Name);
}

[VB.NET]

Private Sub ShowMappingName(ByVal src As Object)


Dim list As IList = Nothing
Dim t As Type = Nothing

If TypeOf (src) Is Array Then


t = src.GetType()
list = CType(src, IList)
Else
If TypeOf src Is IListSource Then
src = CType(src, IListSource).GetList()
End If
If TypeOf src Is IList Then
t = src.GetType()
list = CType(src, IList)
Else
MessageBox.Show("Error")
Return
End If
End If

If TypeOf list Is ITypedList Then


MessageBox.Show(CType(list, ITypedList).GetListName(Nothing))
Else
MessageBox.Show(t.Name)
End If
End Sub

5.77 I have a derived DataGridColumnStyle. From within my Paint override, how can I get at other values
in the DataGrid?

You can get a referernce to the DataGrid with code such as:

Dim grid As DataGrid = Me.DataGridTableStyle.DataGrid

Once you have the grid, you can use an indexer to get the value of any particular column on the same row.

Dim someValue as Object = grid(rowNum, 5) ' value in column 5....

5.78 How do I retrieve the current row from a DataTable bound to a DataGrid after the grid has been
sorted?

In an unsorted DataGrid bound to a DataTable, you can get a reference to a row in the DataTable through
the DataGrid.CurrentRowIndex.

[C#]
DataTable dt = (DataTable) this.dataGrid1.DataSource;
DataRow dr = dt.Rows[this.dataGrid1.CurrentRowIndex);
[VB.NET]
Dim dt As DataTable = Me.DataGrid1.DataSource
Dim dr as DataRow = dt.Rows(Me.DataGrid1.CurrentRowIndex)

But if the grid has been sorted, you can no longer get at the current row in the table through the grid's
CurrentRowIndex. But for both unsorted and sorted grids, you can get at the current row through the
BindingContext and the Current property of the BindingManagerBase.

[C#]
BindingManagerBase bm = this.dataGrid1.BindingContextr[this.dataGrid1.DataSource,
this.dataGrid1.DataMember];
DataRow dr = ((DataRowView)bm.Current).Row;
[VB.NET]
Dim bm As BindingManagerBase = Me.DataGrid1.BindingContext(Me.DataGrid1.DataSource,
Me.DataGrid1.DataMember)
Dim dr As DataRow = CType(bm.Current, DataRowView).Row

5.79 How can I catch when the user clicks off the grid, say to close the form?

You can catch clicking off a DataGrid in the DataGrid.Validated event. But this event is also hit when you
use the Tab key to move around the grid. So, if you want to catch it exclusively for clicking off the grid,
you have to ignore the event due to the tab. One way to do this is to derive DataGrid and override
ProcessDialogKey, noting whether the key is a tab before processing it. Then in your Validated event
handler, you can check for this tab. Here are some snippets.

[C#]
//the handler that checks the derived grid's field inTabKey
private void dataGrid1_Validated(object sender, System.EventArgs e)
{
if(!this.dataGrid1.inTabKey)
{
Console.WriteLine( "Clicked off grid");
}
else
this.dataGrid1.inTabKey = false;
}

//derived class
public class MyDataGrid: DataGrid
{
public bool inTabKey = false;

protected override bool ProcessDialogKey(System.Windows.Forms.Keys


keyData)
{
inTabKey = keyData == Keys.Tab;
return base.ProcessDialogKey( keyData);
}
}

[VB.NET]
'the handler that checks the derived grid's field inTabKey
Private Sub dataGrid1_Validated(sender As Object, e As System.EventArgs)
If Not Me.dataGrid1.inTabKey Then
Console.WriteLine("Clicked off grid")
Else
Me.dataGrid1.inTabKey = False
End If
End Sub 'dataGrid1_Validated

'derived class
Public Class MyDataGrid
Inherits DataGrid

Public inTabKey As Boolean = False

Protected Overrides Function ProcessDialogKey(keyData As System.Windows.Forms.Keys) As


Boolean
nTabKey = keyData = Keys.Tab
Return MyBase.ProcessDialogKey(keyData)
End Function 'ProcessDialogKey
End Class 'MyDataGrid

5.80 How can I get a CheckBox column in a DataGrid to react to the first click?

When you first click into a checkbox column, the checked state of the cell does not change. One way you
can make the checked state change on the first click is to handle the grid's MouseUp event, and change the
check value there.

[VB.Net}
Private myCheckBoxCol As Integer = 9 'my checkbox column
Private Sub DataGrid2_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles
DataGrid2.MouseUp
Dim hti As DataGrid.HitTestInfo = Me.dataGrid2.HitTest(e.X, e.Y)
Try
If hti.Type = DataGrid.HitTestType.Cell AndAlso hti.Column = myCheckBoxCol Then
Me.dataGrid2(hti.Row, hti.Column) = Not CBool(Me.dataGrid2(hti.Row, hti.Column))
End If
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub 'dataGrid2_MouseUp

[C#]
private int myCheckBoxCol = 9; //my checkbox column

private void dataGrid2_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)


{
DataGrid.HitTestInfo hti = this.dataGrid2.HitTest(e.X, e.Y);
try
{
if( hti.Type == DataGrid.HitTestType.Cell &&
hti.Column == myCheckBoxCol)
{
this.dataGrid2[hti.Row, hti.Column] = ! (bool) this.dataGrid2[hti.Row, hti.Column];
}
} catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}

5.81 How can I use events to restrict key input to grid cells?

If you make sure your DataGrid is using a DataGridTableStyle, then you can access the TextBox through
the GridColumnStyles collection and hook the event there. Here is some code....

[C#]
//in formload
this.dataGrid2.DataSource = this.dataSet11.Customers; // set the data source

//make sure grid has a tablestyle


DataGridTableStyle ts = new DataGridTableStyle();
ts.MappingName = this.dataSet11.Customers.TableName;
this.dataGrid2.TableStyles.Add(ts);

//now we can wire up wire up events for columns 1 and 4 ....


DataGridTextBoxColumn tbc = (DataGridTextBoxColumn)ts.GridColumnStyles[0];
tbc.TextBox.KeyPress += new KeyPressEventHandler(CellKeyPress);

tbc = (DataGridTextBoxColumn)ts.GridColumnStyles[3];
tbc.TextBox.KeyPress += new KeyPressEventHandler(CellKeyPress);.....

//the handler
private void CellKeyPress(object sender, KeyPressEventArgs e)
{
//don't allow 1's
if(e.KeyChar == '1')
e.Handled = true;
}

[VB.NET]
'in formload
Me.dataGrid2.DataSource = Me.dataSet11.Customers ' set the data source

'make sure grid has a tablestyle


Dim ts As New DataGridTableStyle()
ts.MappingName = Me.dataSet11.Customers.TableName
Me.dataGrid2.TableStyles.Add(ts)

'now we can wire up wire up events for columns 1 and 4 ....


Dim tbc as DataGridTextBoxColumn = CType(ts.GridColumnStyles(0), DataGridTextBoxColumn)
AddHandler tbc.TextBox.KeyPress, AddressOf CellKeyPress

tbc = CType(ts.GridColumnStyles(3), DataGridTextBoxColumn)


AddHandler tbc.TextBox.KeyPress, AddressOf CellKeyPress
.....

'the handler
Private Sub CellKeyPress(sender As Object, e As KeyPressEventArgs)
'don't allow 1's
If e.KeyChar = "1"c Then
e.Handled = True
End If
End Sub 'CellKeyPress

5.82 How can I format columns in my DataGrid without explicilty adding DataGridColumnStyles?

To format column output, you do not have to explicitly add DataGridColumns for each column provided
you do add a DataGridTableStyle to your DataGrid prior to setting the DataSource property. When you set
the DataSource property with a DataGrid that has a tablestyle with an empty columnstyle collection, the
framework generates default columnstyle objects for each column in the datasource. You can then access
these columnstyles directly and set properties in them such as Format, HeaderText and Width.

Download working samples here (VB.NET, C#).

Dim dataTableName As String = "theTable"

'add a tablestyle to the grid so there will be custom columnstyles available


' after the datasource has been set....
Dim ts As New DataGridTableStyle()
ts.MappingName = dataTableName

Me.dataGrid1.TableStyles.Add(ts)
Me.dataGrid1.DataSource = GetTheTable(dataTableName)

'now default customcolumnstyles have been created, so we can use them to set properties
Dim dgtbc As DataGridTextBoxColumn

'format the int


dgtbc = dataGrid1.TableStyles(0).GridColumnStyles(0)
If Not (dgtbc Is Nothing) Then
dgtbc.Format = "n0"
End If

'format the double


dgtbc = dataGrid1.TableStyles(0).GridColumnStyles(1) '
If Not (dgtbc Is Nothing) Then
dgtbc.Format = "f3" ' 0r "#.000";
End If

'format the double as currency


dgtbc = dataGrid1.TableStyles(0).GridColumnStyles(2) '
If Not (dgtbc Is Nothing) Then
dgtbc.Format = "c4"
End If

'format the date


dgtbc = dataGrid1.TableStyles(0).GridColumnStyles(3) '
If Not (dgtbc Is Nothing) Then
dgtbc.Format = "d" ' or "g" or "u" or whatever format you want to see
dgtbc.Width = 100 'size it
End If

5.83 How can I auto-adjust keyboard input? For example, make typing 12312002 be taken as a valid date,
12/31/2002.

One possible solution is that as you move off the cell, you get the typed value, and modify it before it is
passed onto the DataGrid for its standard processing.

One problem is that there are several ways to leave the cell, and you would want to handle each (depending
upon your needs). You can leave the cell by clicking on another cell, by tabbing off the cell, by arrowing off
the cell, and by pressing Enter on an edited cell.

Another problem is that you want to catch these actions early enough to make a change in the typed value
that can be passed onto the DataGrid itself. To catch the typed entries before they are handed off to the
DataGrid, you have to gain access to the DataGridTextBoxColumn's embedded TextBox. This requires that
your DataGrid either has explicitly had these columns styles added to it, or that you miminally add a
DataGridTableStyle to your DataGrid so the Framework generates ColumnsStyle objects for you.

To solve these problems, you can derive the dataGrid and override OnMouseDown, OnProcessDialogKey,
and OnProcessPreviewKey. The last override will handle both the arrowing off the cell and pressing Enter
on an edited cell.

You can download a sample (C#, VB.NET) that implements this technique.

5.84 Can I display the rows in my datagrid in a free-form layout using textboxes on a panel?

Here is a VB and C# sample showing how you might do this.

The idea is to add textboxes and lables to a panel with whatever layout you want to use.

Then use DataBindings.Add calls to bind the textboxes to columns in your grid (actually in your grid's
datasource). Then, since the grid and the textboxes share the same BindingContext, you can move the
BindingManagerBase.Position property to scroll through the rows in your grid, and the textboxes will
remain in sync. You can hide the grid just to show the textboxes if you do not want the grid to have a
presence. Also, any edits in the textboxes will appear in the DataGrid and vice versa.
5.85 How can I tell whether a scrollbar is visible in my DataGrid is visible?

If you are using a derived DataGrid, then you can check the Visible property on the protected VertScrollBar
property of DataGrid. So, you could check Me.VertScrollBar.Visible from within your derived DataGrid.

To check it without access to the protected scrollbar properties is a little more work, but possible. One
techigue is to loop through the Controls property of the DataGrid looking for the scrollbar, and then
checking its visible property at that time.

[C#]
//sample usage
bool vSrollBarVisible = this.IsScrollBarVisible(this.dataGrid1);
.....

private bool IsScrollBarVisible(Control aControl)


{
foreach(Control c in aControl.Controls)
{
if (c.GetType().Equals(typeof(VScrollBar)))
{
return c.Visible;
}
}
return false;
}

[VB.NET]
'sample usage
Dim vScrollBarVisible = Me.IsScrollBarVisible(Me.DataGrid1)
......

Private Function IsScrollBarVisible(ByVal aControl As Control) As Boolean


Dim c As Control
For Each c In aControl.Controls
If c.GetType() Is GetType(VScrollBar) Then
Return c.Visible
End If
Next
Return False
End Function

5.86 How do I autosize the columns in my DataGrid so they always fill the the grid's client area?

If you add a DataGridTableStyle to your Datagrid, then you can use the ColWidth property of the
GridColumnStyles to set the width of each column. To dynamically set these widths as the grid is resized,
you can handle the SizeChanged event of the the DataGrid. In your handler, you can compute the width of
each column by dividing the client width minus the width of the row header column by the number of
columns. Now there are a couple of technical points. You have to adjust for a possible vertical scrollbar.
And, you have to adjust things for possible integer rounding in the calculations. To handle this last problem,
the attached samples (both VB and C#) apply the single computed width to all but the last column. And this
last column is just given all the space left. This means the last column may differ in width from the other
columns by a couple of pixels.

5.87 How can I prevent all the cells in my DataGrid from being edited without deriving GridColumnStyle?

One solution is to remove all the editing controls from the DataGrid.Controls collection. Without these
controls, the grid contents cannot be edited. There is a technical problem that requires a little care. You do
not want to delete all the controls in DataGrid.Controls as you would lose your scrollbars.

The code below deletes all controls except the scrollbars. Alternativel, you could also loop through the
controls and only delete the TextBox.

[C#]
ArrayList al = new ArrayList();
foreach(Control c in this.dataGrid1.Controls)
{
if(c.GetType() == typeof(VScrollBar) || c.GetType() == typeof(HScrollBar))
{
al.Add(c);
}
}
this.dataGrid1.Controls.Clear();
this.dataGrid1.Controls.AddRange((Control[]) al.ToArray(typeof(Control)));

[VB.NET]
Dim al As New ArrayList()
Dim c As Control
For Each c In Me.dataGrid1.Controls
If c.GetType() = GetType(VScrollBar) Or c.GetType() = GetType(HScrollBar) Then
al.Add(c)
End If
Next c
Me.dataGrid1.Controls.Clear()
Me.dataGrid1.Controls.AddRange(CType(al.ToArray(GetType(Control)), Control()))

5.88 How can I prevent the plus-minus icon that appears next to the row header when I have a datagrid
displayed bound to a datasource that has a relation defined?

Set the
DataGrid.AllowNavigation

property to false.

5.89 How can I display master-details-details in three separate grids?

Here is a sample (both VB and C#) that illustrates how to have a parent table whcih has a related child
table, which also has a related grandchild table.

Below are some code snippets. The trick is to always make the main parent table be the DataSource for all
the grid, and then set the DataMember to be the relation name where teh relation starts at the parent table.
This means the DisplayMember for the Child table is "ParentToChild", the name of that relation. And, the
DisplayMember for the grandchild grid is "ParentToChild.ChildToGrandChild" whcih defines the relation
starting at the parent grid through the child grid.

Dim dSet As New DataSet()

'get the tables


Dim parentTable As DataTable = GetParentTable()
Dim childTable As DataTable = GetChildTable()
Dim grandChildTable As DataTable = GetGrandChildTable()
dSet.Tables.AddRange(New DataTable() {parentTable, childTable, grandChildTable})

'setup the relations


Dim parentColumn As DataColumn = parentTable.Columns("parentID")
Dim childColumn As DataColumn = childTable.Columns("ParentID")
dSet.Relations.Add("ParentToChild", parentColumn, childColumn)

parentColumn = childTable.Columns("childID")
childColumn = grandChildTable.Columns("ChildID")
dSet.Relations.Add("ChildToGrandChild", parentColumn, childColumn)

'set the grids


Me.dataGrid1.DataSource = parentTable

Me.dataGrid2.DataSource = parentTable
Me.dataGrid2.DataMember = "ParentToChild"

Me.dataGrid3.DataSource = parentTable
Me.dataGrid3.DataMember = "ParentToChild.ChildToGrandChild"

Me.dataGrid1.AllowNavigation = False
Me.dataGrid2.AllowNavigation = False
Me.dataGrid3.AllowNavigation = False
5.90 In my datagrid, if I press tab to enter a column using a derived columnstyle, the column does not
receive focus. Why?

This behavior can be seen when you embedded a control like a textbox or combobox in your derived
GridColumnStyle. If you press the tabkey slowly, you may see the cell get focus on the downkey and the
cell lose focus on the upkey. One way to avoid this problem is to subclass the embedded control, and
override its WndProc method, ignoring the KeyUp.

[C#]
public class MyCombo : ComboBox
{
private const int WM_KEYUP = 0x101;

protected override void WndProc(ref System.Windows.Forms.Message m)


{
if(m.Msg == WM_KEYUP)
{
return; //ignore the keyup
}
base.WndProc(ref m);
}
}

[VB.NET]
Public Class MyTextBox
Inherits TextBox
Private WM_KEYUP As Integer = &H101

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)


If m.Msg = WM_KEYUP Then
Return 'ignore the keyup
End If
MyBase.WndProc(m)
End Sub 'WndProc
End Class 'MyTextBox

5.91 How can I detect when a cell starts being edited, not when it becomes current?

You can use the CurrentCellChanged event to detect when the currentcell changes position. But this event
will not allow you to catch the start of a cell being edited.

One way you can do this is to catch the TextChanged event in the embedded TextBox within the cell. If the
text changes, then it might be the beginning of a cell edit provided the text in the TextBox differs from the
stored value from the DataSource. The reason you need to check for a different value between the grid
DataSource and the TextBox contents is that the TextChanged event is fired initially when the TextBox is
initialized when the cell becomes current and moves the value from the grid ataSource to the TextBox. You
also have to ignore subsequent hits of TextChanged as the same cell continues to be edited. Here is both a
VB and C# sample that implements this strategy to flagged current cell start editing.

© 2001-06 Copyright George Shepherd.

6. Windows Forms Docking FAQ Home


6.1 How can I make a control occupy all the client area of a form?
6.2 How can I make my control automatically grow when the parent form is sized?
6.3 What is the difference between a form's Anchor property and a form's Dock property?

6.1 How can I make a control occupy all the client area of a form?

private void Form1_Load(object sender, System.EventArgs e)


{
Bitmap newBmp = new Bitmap(100, 100);
Graphics g = Graphics.FromImage(newBmp);
g.FillRectangle(new SolidBrush(Color.Red), 0, 0, 33, 100);
g.FillRectangle(new SolidBrush(Color.White), 34, 0, 33, 100);
g.FillRectangle(new SolidBrush(Color.Blue), 68, 0, 33, 100);
pictureBox1.Image = newBmp; //pictureBox1 was dropped on the form
}

6.2 How can I make my control automatically grow when the parent form is sized?

Change the control's Anchor property so that it is anchored on all 4 sides.

Please note that you can only have 1 control per form anchored in this manner (all 4 sides). And other
controls on the form should be anchored by their sides that are not adjacent to special control anchored on
all 4 sides.

6.3 What is the difference between a form's Anchor property and a form's Dock property?

G. G. Arun Ganesh discusses these properties in Working with Anchoring and Docking Properties in C# on
C# Corner.

© 2001-06 Copyright George Shepherd.

7. Windows Forms Keyboard Handling FAQ Home


7.1 How can I prevent a control from getting a particular keystroke?
7.2 How can I tell if an ALT, Shift or CTL key is pressed without catching an event?
7.3 How do I check the state of the virtual keys, Caps lock for example?
7.4 How can I simulate keyboard input in my application?
7.5 How can I catch keyboard messages on a application-wide basis?
7.6 How can I listen for certain keys at the Form level irrespective of which Control has the focus?

7.1 How can I prevent a control from getting a particular keystroke?

You can handle the control's KeyPress event and indicate the key has been handled. Below is code that
prevents a TextBox from getting an 'A' and the return key.

private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)


{
if(e.KeyChar == (char)13 || e.KeyChar == 'A')
e.Handled = true;
}

7.2 How can I tell if an ALT, Shift or CTL key is pressed without catching an event?

Use the static property Control.ModifierKeys.


Console.WriteLine(Control.ModifierKeys);
if( (Control.ModifierKeys & Keys.Shift) != 0)
Console.WriteLine("the shift key is down");
if( (Control.ModifierKeys & Keys.Alt) != 0)
Console.WriteLine("the alt key is down");
if( (Control.ModifierKeys & Keys.Control) != 0)
Console.WriteLine("the control key is down");

7.3 How do I check the state of the virtual keys, Caps lock for example?

If the Control.ModifierKeys doesn't address your issue, then use Platform Invoke and call GetKeyState
directly.

Declare this class first:

[
ComVisibleAttribute(false),
SuppressUnmanagedCodeSecurityAttribute()
]
internal class NativeMethods
{
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true,
CallingConvention=CallingConvention.Winapi)]
public static extern short GetKeyState(int keyCode);

public static int HIWORD(int n)


{
return ((n >> 16) & 0xffff/*=~0x0000*/);
}

public static int LOWORD(int n)


{
return (n & 0xffff/*=~0x0000*/);
}
}

Then when you want to check if Caps is down or ON, call:

short state = NativeMethods.GetKeyState(0x14 /*VK_CAPTIAL*/);

bool capsKeyDown = NativeMethods.HIWORD(state);


bool capsKeyON = NativeMethods.LOWORD(state);
7.4 How can I simulate keyboard input in my application?

This can be done through the SendKeys class in the System.Windows.Forms namespace. Check it out in the
MS help documentation.

7.5 How can I catch keyboard messages on a application-wide basis?

You can implement the IMessageFilter interface in your main form. This amounts to adding an override for
PreFilterMessage, and looking for the particular message you need to catch. Here are code snippets that
catch an escape key on a keydown. You can download a sample project(C#, VB). In the sample, there are
two forms, with several controls. You'll notice that no matter what form or control has input focus, the
escape key is caught in the PreFilterMessage override.

[C#]
public class MyMainForm : System.Windows.Forms.Form, IMessageFilter
{
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;

public bool PreFilterMessage(ref Message m)


{
Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;
if(m.Msg == WM_KEYDOWN && keyCode == Keys.Escape)
{
Console.WriteLine("Ignoring Escape...");
return true;
}
return false;
}
....
....
....
private void MyMainForm_Load(object sender, System.EventArgs e)
{
Application.AddMessageFilter(this);
}
}

[VB.NET]
Public Class MyMainForm
Inherits System.Windows.Forms.Form
Implements IMessageFilter

Private WM_KEYDOWN As Integer = &H100


Private WM_KEYUP As Integer = &H101
Public Function PreFilterMessage(ByRef m As Message) As Boolean
Dim keyCode As Keys = CType(CInt(m.WParam), Keys) And Keys.KeyCode
If m.Msg = WM_KEYDOWN And keyCode = Keys.Escape Then
Console.WriteLine("Ignoring Escape...")
Return True
End If
Return False
End Function 'PreFilterMessage
....
....
....
Private Sub MyMainForm_Load(sender As Object, e As System.EventArgs)
Application.AddMessageFilter(Me)
End Sub 'MyMainForm_Load
End Class 'MyMainForm

7.6 How can I listen for certain keys at the Form level irrespective of which Control has the focus?

When the Form.KeyPreview property is set to true, the Form's KeyPress, KeyDown and KeyUp events will
be fired even before the Control with the focus' corresponding events. You may choose to forward these
message to the Control after processing them in the Form's event handlers (this happens by default) or set
the e.Handled property to true (in the event argument) to prevent the message from being sent to the
Control with focus.

© 2001-06 Copyright George Shepherd.

8. Windows Forms Layout FAQ Home


8.1 How can I programmatically set the initial position of a Form so that it is displayed properly after
calling ShowDialog()?
8.2 How do I create a custom layout engine?
8.3 I have a form with several controls on it. As I size the form, the controls are being resized
continuously. Is it possible to postpone changing the controls position until the resizing is complete?
8.1 How can I programmatically set the initial position of a Form so that it is displayed properly after
calling ShowDialog()?

In addition to setting the Location property of the form, make sure you also set the StartPosition property of
the form to FormStartPosition.Manual.

8.2 How do I create a custom layout engine?

Chris Anderson discusses how to implement a custom layout engine and gives sample code in an article on
gotnetdot.com.

8.3 I have a form with several controls on it. As I size the form, the controls are being resized continuously.
Is it possible to postpone changing the controls position until the resizing is complete?

Shawn Burke suggested this solution in a response on the


microsoft.public.dotnet.framework.windowsforms newsgroup. The idea is to do the painting on Idle. This
means you simple invalidate when being sized and then do your full paint when the size completes. Here is
the code that you would add to your form.

bool idleHooked = false;


protected override void OnResize(EventArgs e)
{
if (!idleHooked)
{
Application.Idle += new EventHandler(OnIdle);
}
}

private void OnIdle(object s, EventArgs e)


{
Invalidate();
PerformLayout();
if (idleHooked)
{
Application.Idle -= new EventHandler(OnIdle);
}
}
© 2001-06 Copyright George Shepherd.

9. Windows Forms Licensing FAQ Home


9.1 How does .NET support licensing?
9.2 How do I find the file version of an EXE?

9.1 How does .NET support licensing?

LicFileLicenseProvider is the only license provider shipped with .NET. A good discusion of licensing
techniques along with sample code can be found in an article by Mike Harsh at gotnetdot.com.

9.2 How do I find the file version of an EXE?

Use System.Diagnostics.FileVersionInfo.

© 2001-06 Copyright George Shepherd.

10. Windows Forms Menus FAQ Home


10.1 How do I clone menus, insert menus, use popup menus, etc.
10.2 How do I add a context menu to a control?
10.3 When using the ContextMenu on multiple Controls, how do I know on which Control the right
click was performed?
10.4 How do menu shortcuts work?
10.5 How do I make the context menu appear only when clicked at certain portions of the Control?
10.6 How do I prevent the context menu from showing up on certain keyboard keys (like Keys.Apps)?
10.7 How do I know when a menu is closed/started so that I can refresh my status bar?
10.8 Is there an Idle event which will get fired from which I could update my menu item's enabled state?
10.9 How do I cancel a context menu programatically?
10.10 Is there an easy way to create the "Window" menu that shows the list of child forms open?
10.11 How can I work around my menu shortcuts from showing up incorrectly when I use Ctrl+Number?
10.12 How do I control the position of the context menu when it is invoked via the keyboard?
10.13 How do I disable the default context menu of a textbox?
10.14 How can I make the context menu to close after a set time interval?
10.15 How can I add an icon to my menu items?
10.16 How to add a Separator in a menu?
10.17 How can I enable the mnemonics (underline) to show when my application is launched?

10.1 How do I clone menus, insert menus, use popup menus, etc.

Check out G. G. Arun Ganesh's article Working with Menus in C# on C# Corner.

10.2 How do I add a context menu to a control?

The frame will manage a context menu for you if you set the control's ContextMenu property. Here is some
code adding a context menu to a Label.

//Add Menus in your form's constructor...


this.pictureContextMenu = new ContextMenu();
this.pictureContextMenu.MenuItems.Add("&Color",
new EventHandler(Color_Clicked));
this.pictureContextMenu.MenuItems.Add("&Font",
new EventHandler(Font_Clicked));
label1.ContextMenu = this.pictureContextMenu;
//
// TODO: Add any constructor code after InitializeComponent call
//
}

private void Font_Clicked(object sender, System.EventArgs e)


{...}

private void Color_Clicked(object sender, System.EventArgs e)


{ ... }

10.3 When using the ContextMenu on multiple Controls, how do I know on which Control the right click
was performed?

The ContextMenu.SourceControl property will specify the latest Control on which the context menu was
shown.

10.4 How do menu shortcuts work?


The focused control's ProcessCmdKey will be called first.

1) The Control class implementation of this method will check if there is a ContextMenu associated with
the Control and if so let the context menu handle the shortcut.

2) If not handled, the ProcessCmdKey of the parent will be called recursively until the Form is reached.

3) When the Form is reached it's MainMenu will be requested to handle the key.

You can override ProcessCmdKey of any Control and interrupt the normal processing. Note that you can
also override the ProcessCmdKey method is the MainMenu and ContextMenu classes (this is not
documented) to override default processing.

10.5 How do I make the context menu appear only when clicked at certain portions of the Control?

You can listen to the Popup event, determine where the mouse was clicked and selectively make the menu
items visible in the menu as follows:

// In C#
private void contextMenu1_Popup(object sender, System.EventArgs e)
{
// Get current mouse click position in the control (assuming pictureBox1 is the control):
Point ptClick = this.pictureBox1.PointToClient(Control.MousePosition);
// Get the rectangle where you want to show the context menu.
Rectangle preferredClickRect = new Rectangle(0, 0, 50, 50);
if(preferredClickRect.Contains(ptClick))
{
// Show all the menu items so that the menu will appear
foreach(MenuItem item in this.contextMenu1.MenuItems)
item.Visible = true;
}
else
{
// Hide all the menu items so that the menu will not appear
foreach(MenuItem item in this.contextMenu1.MenuItems)
item.Visible = false;
}
}

' In VB.Net
Private Sub contextMenu1_Popup(ByVal sender As Object, ByVal e As System.EventArgs)
' Get current mouse click position in the control (assuming pictureBox1 is the control):
Dim ptClick As Point = Me.pictureBox1.PointToClient(Control.MousePosition)
' Get the rectangle where you want to show the context menu.
Dim preferredClickRect As Rectangle = New Rectangle(0,0,50,50)
If preferredClickRect.Contains(ptClick) Then
' Show all the menu items so that the menu will appear
Dim item As MenuItem
For Each item In Me.contextMenu1.MenuItems
item.Visible = True
Next
Else
' Hide all the menu items so that the menu will not appear
Dim item As MenuItem
For Each item In Me.contextMenu1.MenuItems
item.Visible = False
Next
End If
End Sub

10.6 How do I prevent the context menu from showing up on certain keyboard keys (like Keys.Apps)?

Override WndProc in your Control and do the following. You should then listen to keyup and show the
context menu yourself.

[C#]
protected override void WndProc(ref Message m)
{
if(m.Msg == 0x7b /*WM_CONTEXTMENU*/ )
{
return;
}
if(m.Msg == 0x101 /*WM_KEYUP*/)
{
Keys keys = (Keys)m.WParam.ToInt32();
// Prevent this key from being processed.
if(keys == Keys.Apps)
return;
}
base.WndProc(ref m);
}

[VB.Net]
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = 0x7b Then 'WM_CONTEXTMENU
Return
End If
If m.Msg = 0x101 Then 'WM_KEYUP
Dim keys As Keys = CType(m.WParam.ToInt32(), Keys)
' Prevent this key from being processed.
If keys = Keys.Apps Then
Return
End If
End If
MyBase.WndProc( m)
End Sub

10.7 How do I know when a menu is closed/started so that I can refresh my status bar?

There are MenuComplete and MenuStart events in the Form that will inform you of the corresponding
menu events in the Form.

10.8 Is there an Idle event which will get fired from which I could update my menu item's enabled state?

This used to be a very useful feature in MFC. You can do something similar with the
System.Windows.Forms.Application.Idle event which will get fired when the app becomes Idle. Where you
could parse through all the menu items and update their states.

10.9 How do I cancel a context menu programatically?

First keep track of which control is showing the ContextMenu by listening to the menu's Popup event and
querying for the SourceControl.

Then when you are ready to cancel the popup, do as follows:

[C#]
[DllImport("user32.dll", CharSet=CharSet.Auto)]
extern internal static IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

private void Timer_Tick(object sender, EventArgs e)


{
if(menuSourceControl != null)
SendMessage(menuSourceControl.Handle, 0x001F/*WM_CANCELMODE*/, IntPtr.Zero,
IntPtr.Zero);
}

[VB.Net]
_
extern internal static IntPtr SendMessage(IntPtr hWnd, Integer msg, IntPtr wParam, IntPtr lParam)

Private Sub Timer_Tick(ByVal sender As Object, ByVal e As EventArgs)


If Not menuSourceControl Is Nothing Then
SendMessage(menuSourceControl.Handle, 0x001F, IntPtr.Zero, IntPtr.Zero)
End If

End Sub

10.10 Is there an easy way to create the "Window" menu that shows the list of child forms open?

Create a "Window" menu in you mdi parent form's menu and then drop another MenuItem into it, setting
it's MdiList propety to true. It will then expand to show all the available mdi children during runtime.

10.11 How can I work around my menu shortcuts from showing up incorrectly when I use Ctrl+Number?

When you assign Ctrl1, Ctrl2 etc as shorcuts for menuitems they show up as Ctrl+D1, Ctrl+D2. This can be
worked around by creating and adding the menuitem through code as demonstrated below:

[C#]
//Create the menuitem
MenuItem mymenuItem = new MenuItem();
//ShortCut
mymenuItem.Shortcut = System.Windows.Forms.Shortcut.Ctrl1;
//Add Event Handler for the menuitem
mymenuItem.Click +=new EventHandler(this.mymenuItem_Click);
//ShortCut Text to be displayed
mymenuItem.Text = "My MenuItem" +"\t"+ "Ctrl+1";
//hide shortcut
mymenuItem.ShowShortcut = false;
//Add it to the bottom of the first menu
this.mainMenu1.MenuItems[0].MenuItems.Add(mymenuItem);

[VB.NET]
'Create the menuitem
Dim mymenuItem As MenuItem = New MenuItem()
'ShortCut
mymenuItem.Shortcut = System.Windows.Forms.Shortcut.Ctrl1
'Add Event Handler for the menuitem
mymenuItem.Click +=New EventHandler(Me.mymenuItem_Click)
'ShortCut Text to be displayed
mymenuItem.Text = "My MenuItem" +"\t"+ "Ctrl+1"
'hide shortcut
mymenuItem.ShowShortcut = False
'Add it to the bottom of the first menu
Me.mainMenu1.MenuItems(0).MenuItems.Add(mymenuItem)

10.12 How do I control the position of the context menu when it is invoked via the keyboard?

Normally, the context menu will be shown at the center of the control when the keyboard is used to invoke
the context menu of a control (Shift+F10, for example). You can customize the location as follows.

1. Override WndProc in the grid and check if the Message.Msg is WM_CONTEXTMENU (0x007b)
2. If so, check if the Message.LParam is -1, which means this was due to a keyboard message as
opposed to the user right-clicking the mouse.
3. Now, call the associated ContextMenu's Show method explicity at the selected row position.
4. Make sure NOT to call the base class after showing the menu explicitly.

protected override void WndProc(ref Message m)


{
if(m.Msg == 0x007B /*WM_CONTEXTMENU*/)
{
// LParam == -1 means that this is due to a keyboard message
if((int)m.LParam == -1)
{
this.contextMenu.Show();
return;
}
}
}

[VB.Net]
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = 0x007B Then 'WM_CONTEXTMENU
' LParam == -1 means that this is due to a keyboard message
If (CType(m.LParam,Integer)) = -1 Then
Me.contextMenu.Show()
Return
End If
End If
End Sub

10.13 How do I disable the default context menu of a textbox?

To prevent the default context menu of a TextBox from showing up, assign a empty context menu as shown
below:

[C#]
textBox1.ContextMenu = new ContextMenu();

[VB.Net]
textBox1.ContextMenu = New ContextMenu()

10.14 How can I make the context menu to close after a set time interval?

To automatically close the context menu after a set time interval, you can use a Timer and send a ESC key
stroke after the desired time interval as shown:

[C#]
private void timer1_Tick(object sender, System.EventArgs e)
{
SendKeys.Send("{ESC}");
timer1.Stop();
}
private void contextMenu1_Popup(object sender, System.EventArgs e)
{
//set interval to 5 seconds
timer1.Interval = 5000;
timer1.Start();
}

[VB.Net]

Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs)


SendKeys.Send("{ESC}")
timer1.Stop()
End Sub
Private Sub contextMenu1_Popup(ByVal sender As Object, ByVal e As System.EventArgs)
'set interval to 5 seconds
timer1.Interval = 5000
timer1.Start()
End Sub

10.15 How can I add an icon to my menu items?

You need to implement an owner drawn menu to add icons to it. Take a look at the sample on .netPlus.

10.16 How to add a Separator in a menu?

contextmenu.MenuItems.Add("-");

10.17 How can I enable the mnemonics (underline) to show when my application is launched?

Usually the underline appears only after you press the ALT Key, but you can enable it by changing the
Operating System Settings. On Windows XP, Right Click Desktop to bring up the Display Properties
Dialog and then choose Appearance tab and then the Effects Button and uncheck the checkbox "Hide
Underlined letters for keyboard navigation until I press the ALT Key".

© 2001-06 Copyright George Shepherd.

11. Windows Forms Mouse Handling FAQ Home


11.1 How can I resize a borderless form with a rubber-band effect?
11.2 How do I get a mouse cursor position in my control's client coordinates?
11.3 How can I catch the mouse being over a control?
11.4 How do I set the mouse cursor position?
11.5 How can I reset the OnMouseHover timer so that it will fire again without the mouse having to
leave the client area of a control?
11.6 How can I drag a window if it doesn't have a title bar or border?
11.7 How can I determine if a mouse button is pressed and moving over my form?
11.8 Why am I not receiving MouseLeave messages in a Control in my Form?
11.1 How can I resize a borderless form with a rubber-band effect?

Simon Bond has sample code at C# Corner that implements this sizing technique. Zhanbo Sun suggests a
modification that handles a problem he spotted with the original code.

11.2 How do I get a mouse cursor position in my control's client coordinates?

Use the Position property of the Cursor class found in the System.Windows.Forms namespace. Here is code
that will flag whether the mouse is over button1.

Point ptCursor = Cursor.Position;


ptCursor = PointToClient(ptCursor);
if( button1.Bounds.Contains(ptCursor) )
{
//mouse over button1
//....
}
else
{
//mouse not over button1
//....
}

11.3 How can I catch the mouse being over a control?

Add a handler for the control's MouseMove event. This will be hit as the mouse moves over the control's
Bounds rectangle.

11.4 How do I set the mouse cursor position?

The Cursor.Position property is a static property with both get and set methods available. Remember that
the Point object used by the property is in screen coordinates. Here is code that move the mouse position
down 20 points.

Point pt = Cursor.Position;
pt.Y += 20;
Cursor.Position = pt;
11.5 How can I reset the OnMouseHover timer so that it will fire again without the mouse having to leave
the client area of a control?

In the microsoft.public.dotnet.framework.windowsforms newsgroup, T. H. in den Bosch posted the


following suggestion with a potential warning: I found out that calling Control.ResetMouseEventArgs()
does the trick. This is an undocumented internal method, so I don't know if calling it has adverse side
effects.

11.6 How can I drag a window if it doesn't have a title bar or border?

You can drag such a window by using Win32 APIs to switch the mouse hit to WM_NCLBUTTONDOWN.
The code below will allow you to drag by mousing down anywhere in the form's clientarea as long as you
don't hit a child control on the form.

using System.Runtime.InteropServices;
............
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HTCAPTION = 0x2;

[DllImportAttribute ("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

[DllImportAttribute ("user32.dll")]
public static extern bool ReleaseCapture();

private void Form2_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)


{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}

Here is a solution posed by Jacob Grass (Abiliti Solutions) that does not rely on InteropServices.

Private blnMoving As Boolean = False


Private MouseDownX As Integer
Private MouseDownY As Integer

Private Sub Form1_MouseDown(ByVal sender As Object, _


ByVal e As System.Windows.Forms.MouseEventArgs) Handles Form1.MouseDown
If e.Button = MouseButtons.Left Then
blnMoving = True
MouseDownX = e.X
MouseDownY = e.Y
End If
End Sub

Private Sub Form1_MouseUp(ByVal sender As Object, _


ByVal e As System.Windows.Forms.MouseEventArgs) Handles Form1.MouseUp
If e.Button = MouseButtons.Left Then
blnMoving = False
End If
End Sub

Private Sub Form1_MouseMove(ByVal sender As Object, _


ByVal e As System.Windows.Forms.MouseEventArgs) Handles Form1.MouseMove
If blnMoving Then
Dim temp As Point = New Point()

temp.X = Form1.Location.X + (e.X - MouseDownX)


temp.Y = Form1.Location.Y + (e.Y - MouseDownY)
Form1.Location = temp
End If
End Sub

11.7 How can I determine if a mouse button is pressed and moving over my form?

Catch the form's MouseMove event which is called when the mouse moves over the form. To determine if a
button is pressed during the move, check the event arg's Button property. The code below draw's a line on
the form as the mouse moves over it. The line is red when the left button is pressed, white when the right
button is pressed and blue when no button is pressed.

private Point _point = new Point(-1, -1);


....
private void InitializeComponent()
{
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Name = "Form1";
this.Text = "Form1";
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);
}
....
private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if(_point.X == -1)
_point = new Point(e.X, e.Y);

Color c;
if(e.Button == MouseButtons.Left)
c = Color.Red;
else if(e.Button == MouseButtons.Right)
c = Color.White;
else if(e.Button == MouseButtons.None)
c = Color.Blue;
else
c = this.BackColor;

Point p = new Point(e.X,e.Y);


Graphics g = Graphics.FromHwnd(this.Handle);
Pen pen = new Pen(c,1);
g.DrawLine(pen,_point,p);
_point = p;
pen.Dispose();
}

11.8 Why am I not receiving MouseLeave messages in a Control in my Form?

This usually happens when a Control doesn't know that the mouse has left its bounds following a mouse
enter. This results in the Control not throwing a MouseLeave event for subsequent mouse moves over it.

This is possible if you performed some operation when the mouse was within a Control that made it lose its
mouse capture, for example, opening a top-level window over the Control such that the mouse is now over
this new window.

To work around this problem send a WM_MOUSELEAVE manually to the original Control before the
offending operation.

class NativeMethods
{
[DllImport("user32.dll", CharSet=CharSet.Auto)]
extern public static IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam) ;
}

// Send a WM_MOUSELEAVE manually to a window.


NativeMethods.SendMessage(control.Handle, NativeMethods.WM_MOUSELEAVE, IntPtr.Zero,
IntPtr.Zero);

© 2001-06 Copyright George Shepherd.


12. Windows Forms from MFC FAQ Home
12.1 As a VC++ programmer, what should I look out for when using C#?
12.2 Where can I find a succinct discussion of Windows Forms?
12.3 When I add a destructor to a class, why isn't it hit when my instantiated object goes out of scope?
12.4 How do I convert a string to a double or int? What plays the role of atof and atoi in C#?
12.5 What class or method do I use to retrieve system metrics like the width of a scrollbar?
12.6 In C++, the code "MyClass ht;" creates an object ht on the stack frame. But in C#, this same code
compiles, but gives a runtime error. Why?
12.7 I need to encode the LParam argument of a mouse message. How do I do MakeLong , HiWord and
LoWord type conversions?
12.8 How do you clear the contents of a list box?

12.1 As a VC++ programmer, what should I look out for when using C#?

1] The conditionals in if-statements must calculate to a boolean value. You cannot write something like

if (nUnits) { ... }

where nUnits is a int.

2] All code must reside in a class. There are no global variables per se.

3] Bitwise & and | operators can be used with boolean types as logical operators. The && and || operators
are also used, and do have the "short-cut calculation" behavior found in C++. The & and | operators do not
have this ""short-cut calculation" behavior.

4] Pointers are not available in managed code.

5] In managed code, destructors are not hit immediately when as object goes out of scope. Ie, there is no
deterministic destruction.

12.2 Where can I find a succinct discussion of Windows Forms?

One place to look is Jeff Prosise's article, Windows Forms: A Modern-Day Programming Model for Writing
GUI Applications, from the Feb 2001 MSDN magazine .

A second place is Shawn Burke's articleUsing the Microsoft .NET Framework to Create Windows-based
Applications found in the MSDN Library.

12.3 When I add a destructor to a class, why isn't it hit when my instantiated object goes out of scope?
Your managed code doesn't have a destructor, just a finalizer. The difference is a destructor (as in C++)
fires immediately when an object goes out of scope, but a finalizer is run when the CLR's garbage collector
(GC) gets to your object. It's not determanistic when this will occur, but it's very unlikely to occur right
after the object goes out of scope. It will happen at a later time, however.

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

12.4 How do I convert a string to a double or int? What plays the role of atof and atoi in C#?

You use static members of the Convert class found in the System namespace to handle conversions in the
.NET framework.

string s = "45";
int h = Convert.ToInt32(s);
double d = Convert.ToDouble(s);

12.5 What class or method do I use to retrieve system metrics like the width of a scrollbar?

In the .NET framework, you use the SystemInformation class from the System.Windows.Forms namespace.
This class has comparable information to what GetSystemMetrics() returned in VC6. There is also a Screen
class that contains additions display device properties.

12.6 In C++, the code "MyClass ht;" creates an object ht on the stack frame. But in C#, this same code
compiles, but gives a runtime error. Why?

MyClass ht; does not create any object. Instead, it creates a variable (a reference) of type MyClass, and sets
its value to null. No object is created. To create an object, you need to explicitly call the class contructor
with a new.

MyClass ht = new MyClass();

You can also use ht to refer to an instance of MyClass that has been created (with a new) at some other
point in your code.

MyClass myClass = new MyClass();


......
MyClass ht;
......
ht = myClass; // both ht and myClass are references to the same object...
12.7 I need to encode the LParam argument of a mouse message. How do I do MakeLong , HiWord and
LoWord type conversions?

You can create static methods that encode and decode these values. Here are some.

static int MakeLong(int LoWord, int HiWord)


{
return (HiWord << 16) | (LoWord & 0xffff);
}
static IntPtr MakeLParam(int LoWord, int HiWord)
{
return (IntPtr) ((HiWord << 16) | (LoWord & 0xffff));
}
static int HiWord(int Number)
{
return (Number >> 16) & 0xffff;
}
static int LoWord(int Number)
{
return Number & 0xffff;
}

12.8 How do you clear the contents of a list box?

You have to access the Items of the ListBox using the Items property and clear (or otherwise operate on the
items) these.

this.lb1.Items.Clear();

© 2001-06 Copyright George Shepherd.

13. Windows Forms from VB6 FAQ Home


13.1 How do I draw a line in VB7 as there is no Line command as there was in VB6?
13.2 What is the replacement for VB6's SendKeys statement?
13.3 In VB6, I used control arrays to have a common handler handle events from several controls. How
can I do this in Windows Forms?
13.4 What is different about working with forms in VB.NET? For example, how can I reference one
form from another form?

13.1 How do I draw a line in VB7 as there is no Line command as there was in VB6?

Try this code:

Dim g as Graphics
g = frmMain.CreateGraphics()
g.DrawLine(Pens.Black, new Point(0,0), new
Point(frmMain.ClientRectangle.Width), frmMain.ClientRectangle.Height)
g.Dispose()

This should draw a line from the upper left to the bottom right corner of your application, but only if it's
visible. If this code isn't in the paint event, when something obscures your application and/or it repaints,
this line will *not* be redrawn.

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

Another possible solution that has a design-time element is to use a label with height 1 and FixedSingle
Border. (suggested by Mark Lewis in microsoft.public.dotnet.framework.windowsforms)

13.2 What is the replacement for VB6's SendKeys statement?

It is the Send method from the SendKeys class found in the System.Windows.Forms namespace.

13.3 In VB6, I used control arrays to have a common handler handle events from several controls. How can
I do this in Windows Forms?

You can specify events from different controls be handled by a single method. When you define your
handler, you can list several events that are to be handled by listing them in the Handles argument. This
statement handles three different textbox's TextChanged event.

Private Sub TextsChanged(ByVal sender As System.Object, _


ByVal e As System.EventArgs) _
Handles TextBox1.TextChanged, TextBox2.TextChanged, TextBox3.TextChanged

In the TextsChanged handler, you may need to identify the particular control that fired the event. This
sender parameter holds the control. You can use it with code such as:
Dim eventTextBox as TextBox = sender

13.4 What is different about working with forms in VB.NET? For example, how can I reference one form
from another form?

Check out this Microsoft article on working with multiple forms in VB.NET by Duncan Mackenzie.

© 2001-06 Copyright George Shepherd.

14. Windows Forms Patterns FAQ Home


14.1 How to display a status dialog in a background thread during a long operation and alow the user to
cancel?
14.2 How can I throw my events asynchronously?
14.3 Why are the Tooltips not being shown on a NumericUpDown control?
14.4 How to get the hyperlink and the hyperlink text dragged from IE in my Control's drag-drop event?

14.1 How to display a status dialog in a background thread during a long operation and alow the user to
cancel?

You can do this by starting a new thread and executing Application.Run for the status dialog form when the
background thread starts running. To communicate changes in percentage use BeginInvoke to executes a
specific delegate asynchronously on the thread that the form was created on.

Download the ProgressThread progressthread.zip sample for a complete implementation of a


BackgroundThreadStatusDialog class that shows a status dialog in a separate thread.

In order to use BackgroundThreadStatusDialog from your code you have to update the progess inside your
loop and check the IsCanceled state to detect if the user pressed the Cancel button.

private void button1_Click(object sender, System.EventArgs e)


{
BackgroundThreadStatusDialog statusDialog = new BackgroundThreadStatusDialog();
try
{
for (int n = 0; n < 1000; n++)
{
statusDialog.Percent = n/10;
int ticks = System.Environment.TickCount;
while (System.Environment.TickCount - ticks < 10)
;
if (statusDialog.IsCanceled)
return;
}
statusDialog.Close();
MessageBox.Show(statusDialog.IsCanceled ? "Canceled" : "Success");
}
finally
{
statusDialog.Close();
}
}

14.2 How can I throw my events asynchronously?

You can do so by calling BeginInvoke on your delegates.

Unfortunately, you can't call BeginInvoke() on the event member directly. You can invoke BeginInvoke()
only if the delegate's internal list of sink callbacks (actually other delegates) has only one target in it. If you
have more than one, the delegate throws an exception.

The workaround is to iterate over the event delegate internal invocation list, calling BeginInvoke() on every
one of them. You access the internal list using the GetInvocationList() method.

Here is an example:

public delegate void NumberChangedDelegate(int


num);

public class MySource


{
public event NumberChangedDelegate
m_NumberChangedEvent;
public void FireEventAsynch(int num)
{
Delegate[] delegates =
m_NumberChangedEvent.
GetInvocationList();
foreach(Delegate del in delegates)
{
NumberChangedDelegate sink =
(NumberChangedDelegate)del;
sink.BeginInvoke(num,null,null);
}
}
public void FireEvent(int num)
{
m_ NumberChangedEvent(num);
}
}

From Juval Löwy at www.idesign.net; from his article in the .Net Insight online magazine at
www.fawcette.com.

14.3 Why are the Tooltips not being shown on a NumericUpDown control?

This is because of a bug in the .net framework. When tooltips are set on a control that hosts other controls
within it (like the numeric updown), tooltips are not shown on those child controls. To workaround this
issue, do the following in code:

[C#]
foreach(Control c in this.numericUpDown1.Controls)
{
this.tooltip.SetToolTip(c, "mytooltip");
}

[VB.Net]
Dim c As Control
For Each c In Me.numericUpDown1.Controls
Me.tooltip.SetToolTip(c, "mytooltip")
Next
14.4 How to get the hyperlink and the hyperlink text dragged from IE in my Control's drag-drop event?

Compiled from the newsgroup posts by Andy Fish and Brian:

You can do this in the DragDrop event handler of your control:

[C#]
try
{
//Use e.Data.GetData("UniformResourceLocator") to get the URL
System.IO.Stream ioStream=
(System.IO.Stream)e.Data.GetData("FileGroupDescriptor");
byte[] contents = new Byte[512];
ioStream.Read(contents,0,512);
ioStream.Close();
StringBuilder sb = new StringBuilder();
//The magic number 76 is the size of that part of the
//FILEGROUPDESCRIPTOR structure before the filename starts - cribbed
//from another usenet post.
for (int i=76; contents[i] != 0; i++)
{
sb.Append((char)contents[i]);
}
if (!sb.ToString(sb.Length-4,4).Equals(".url"))
{
throw new Exception("filename does not end in '.url'");
}
filename = sb.ToString(0,sb.Length-4);

}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}

[VB.Net]
Try
'Use e.Data.GetData("UniformResourceLocator") to get the URL
System.IO.Stream ioStream=
CType(e.Data.GetData("FileGroupDescriptor"), System.IO.Stream)
Dim contents() As Byte = New Byte(512) {}
ioStream.Read(contents,0,512)
ioStream.Close()
Dim sb As StringBuilder = New StringBuilder()
'The magic number 76 is the size of that part of the
'FILEGROUPDESCRIPTOR structure before the filename starts - cribbed
'from another usenet post.
Dim i As Integer
For i = 76 To contents(i) 0 Step i + 1
sb.Append(CType(contents(i), Char))
Next
If Not sb.ToString(sb.Length-4,4).Equals(".url") Then
Throw New Exception("filename does not end in '.url'")
End If
filename = sb.ToString(0,sb.Length-4)
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try

© 2001-06 Copyright George Shepherd.

15. Windows Forms Printing FAQ Home


15.1 How do I print a form?
15.2 How do I display the PrintPreview maximized and control its zooming?

15.1 How do I print a form?

I am afraid there is not a very easy way to print a form. You may implement this function with the steps
below:

1. Add a print function to your application.

To do this, you should add a PrintDocument component to your application.


Please drag a PrintDocument from the tool box to your form. After that, you
should create a PrintDialog and add the code to print the document.

private void buttonPrint_Click(object sender, System.EventArgs e)


{
PrintDialog printDialog1 = new PrintDialog();
printDialog1.Document = printDocument1;
DialogResult result = printDialog1.ShowDialog();
if (result == DialogResult.OK)
{
printDocument1.Print();
}
}

For detailed information about print framework, please see "Windows Forms
Print Support" in the MSDN (October 2001).

2. Draw the form when printing.

This step is a little complex. You should handle the PrintPage of the
printDocument1 and draw the form to the printer device. In the event you
may copy the form to an image and then draw it to the printer device.

private void printDocument1_PrintPage(object sender,


System.Drawing.Printing.PrintPageEventArgs e)
{
Graphics graphic = this.CreateGraphics();
Size s = this.Size;
Image memImage = new Bitmap(s.Width, s.Height, graphic);
Graphics memGraphic = Graphics.FromImage(memImage);
IntPtr dc1 = graphic.GetHdc();
IntPtr dc2 = memGraphic.GetHdc();
BitBlt(dc2, 0, 0, this.ClientRectangle.Width,
this.ClientRectangle.Height, dc1, 0, 0, 13369376);
graphic.ReleaseHdc(dc1);
memGraphic.ReleaseHdc(dc2);
e.Graphics.DrawImage(memImage,0,0);
}

The above referenced the article "Screen Capturing a Form in .NET - Using
GDI in GDI+" by Michael Gold. You may find it at:
http://www.c-sharpcorner.com/Graphics/ScreenCaptFormMG.asp

3. Declare the API function.

Please note the BitBlt function used in Step 2. It is an unmanaged


function. You should use DllImportAttribute attribute to import it to your
code. Although, this is the Step 3, you may perform this step any time.

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
System.Int32 dwRop // raster operation code
);

For more information about DllImportAttribute attribute please see:


http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/
frlrfSystemRuntimeInteropServicesDllImportAttributeClassTopic.asp

(from Lion Shi (lion_noreply@microsoft.com) on microsoft.public.dotnet.framework.windowsforms)

15.2 How do I display the PrintPreview maximized and control its zooming?

You can use the WindowState property of the PrintPreviewDialog class to bring the PrintPreview
maximized. To handle zooming, the PrintPreviewDialog has a property, PrintPreviewControl.
PrintPreviewControl owns a Zoom property that allows you to set the zoom factor of the PrintPreview.

© 2001-06 Copyright George Shepherd.

16. Windows Forms Resources FAQ Home


16.1 What are the steps to compiling and using multiple language resources?
16.2 How do I load a BMP file that has been added to my solution as an embedded resource?
16.3 Why doesn't a Form containing an ImageList not open in WinRes?
16.4 Where can I find information on globalization?
16.5 How do I read embedded resources?
16.6 How can I check if a certain resource is included in a assembly?
16.7 How can I save a temporary disk file from an embedded string resource?
16.8 How do I embed a manifest file into my exe?
16.9 How do I read or write resources from code?
16.10 How do I create resources to make culture-aware programs without re-compiling code?
16.11 How do I programmatically use resources to make my programs culturely aware?
16.12 How can I dynamically load a resource file?
16.1 What are the steps to compiling and using multiple language resources?

Localization Sample illustrates how to load different language resources depending upon a parameter
passed in when you run the program from a command line. The sample can display English, French,
Spanish and German words using the same exe. For example, typing Test de on the command line will
count to three in German. Typing Test fr will count to three in French. The argument passed in is used to
determine the culture setting for the resources.

In each folder is a batch file that handles compiling the single exe and multiple resources. The tools
RESGEN and AL are used in these batch files to generate the resources and resource DLL's. Notice the
naming conventions used by the subfolders containing the foreign resource DLLs.

16.2 How do I load a BMP file that has been added to my solution as an embedded resource?

If you add a BMP file to your solution using the File|Add Exisitng Item... menu item, then change the Build
Action property of this BMP file to Embedded Resource, you can then access this resource with code
similar to:

// WindowsApplication6 corresponds to Default Namespace in your project settings.


// subfolders should be the folder names if any, inside which the bmp is added. If the bmp was added to
the top level, you don't have to specify anything here.
string bmpName = "WindowsApplication6.subfolders.sync.bmp";
System.IO.Stream strm = null;
try
{
strm = this.GetType().Assembly.GetManifestResourceStream(bmpName);
pictureBox1.Image = new Bitmap(strm);
// Do the same for Icons
// Icon icon1 = new Icon(strm);
}
catch(Exception e)
{
MessageBox.Show(e.Message);
}
finally
{
if(strm != null)
strm.Close();
}

16.3 Why doesn't a Form containing an ImageList not open in WinRes?

There seems to be a bug in the WinRes utility (1.0) that prevents a form from getting loaded in the WinRes
editor (usually an exception like "Object reference not found" occurs). A quick workaround is to always
name your ImageLists to be of the form "imageListN" (case sensitive; where N is the smallest no. you
could use without a clash with other ImageLists).

16.4 Where can I find information on globalization?

Here are some MSDN globalization samples:


Visual Basic .NET Code Sample: Working with Resource Files
.NET Samples - How To: Globalization and NLS

Also look at the following topic in online help inside IDE.


Developing World-Ready Applications

16.5 How do I read embedded resources?

Check out the entry titled How do I load a BMP file that has been added to my solution as an embedded
resource? in this section. That code can be used for any kind of embedded resource.

16.6 How can I check if a certain resource is included in a assembly?

If a resource is not available in a assembly or in satellite assemblies you will get a message like this "Could
not find any resources appropriate for the specified culture...". You can open your assembly and any related
satellite assemblies in ILDASM (tool that ships with the .NET framework). When your assembly is open in
ILDASM take a look at the manifest file. This contains a list of the resources in your assembly. Usually
such errors are the result of incorrect namespaces being used or from spelling errors.

16.7 How can I save a temporary disk file from an embedded string resource?

//usage: string s = CopyResourceToTempFile(GetType(), "showcase.txt");


//where showcase.txt is an embedded resource

static string CopyResourceToTempFile(Type type, string name)


{
string temp = "";
string nsdot = type.Namespace;
if (nsdot == null)
nsdot = "";
else if (nsdot != "")
nsdot += ".";
Stream stream = type.Module.Assembly.GetManifestResourceStream(nsdot + name);
if (stream != null)
{
StreamReader sr = new StreamReader(stream);
temp = Path.GetTempFileName();
StreamWriter sw = new StreamWriter(temp, false);
sw.Write(sr.ReadToEnd());
sw.Flush();
sw.Close();
}
return temp;
}

16.8 How do I embed a manifest file into my exe?

A Win32 resource must be added to your .exe. The type of the resource must be "RT_MANIFEST" and the
resource id must be "1". An easy way to do this is with Visual Studio.NET:

1. Open your exe in VS (file -> open file)


2. Right click on it and select add resource
3. Click "Import..." from the dialog
4. Select your manifest file
5. In the "Resource Type" field, enter "RT_MANIFEST"
6. In the property grid, change the resource ID from "101" to "1".
7. Save the exe.

From Mike Harsh at gotnetdot.com.

16.9 How do I read or write resources from code?

You can use the ResourceWriter object to create resource files.

Take a look at the discussion and code found on gotdotnet.com

16.10 How do I create resources to make culture-aware programs without re-compiling code?

Placing culture dependent resources in a separate file from your compiled program code allows you to
write applications that can change cultures without having to recompile code to handle different resources.

Take a look at the discussion and code found on gotdotnet.com

16.11 How do I programmatically use resources to make my programs culturely aware?

You can use the ResourceManager object to dynamically load a particular resource based on a selected
culture. This technique allows you to develop culture-aware programs without having to recompile your
application.
Take a look at the discussion and code found on gotdotnet.com

16.12 How can I dynamically load a resource file?

You use the ResourceManager class found in System.Resources to access and control resources.

See the article by Caspar Boekhoudt on C# Corner for a detailed discussion.

© 2001-06 Copyright George Shepherd.

17. Windows Forms Scrolling FAQ Home


17.1 How do I add support for custom scrolling to my own user control?
17.2 Are there any events that get fired when the user scrolls?

17.1 How do I add support for custom scrolling to my own user control?

Windows Forms features a ScrollableControl. This will work in most cases where you know the exact
dimensions of your control and scroll by pixel. See the MSDN Documentation for ScrollableControl for
discussion how to use this control.

Sometimes you may need more customized scrolling, for example if you implemented a text editor and you
want to scroll lines and not pixels.

For more customized scrolling you have to use PInvoke to acces the Win32 ScrollWindow method. The
following code shows how to enable access to the Win32 ScrollWindow method from your code.

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public RECT(Rectangle rect)
{
this.bottom = rect.Bottom;
this.left = rect.Left;
this.right = rect.Right;
this.top = rect.Top;
}

public RECT(int left, int top, int right, int bottom)


{
this.bottom = bottom;
this.left = left;
this.right = right;
this.top = top;
}
}

[DllImport("user32")]
public static extern bool ScrollWindow(IntPtr hWnd, int nXAmount, int nYAmount, ref RECT
rectScrollRegion, ref RECT rectClip);

void MyScrollFunc(int yAmount)


{
RECT r = new RECT(ClientRectangle);
ScrollWindow(Handle, 0, yAmount, ref r, ref r);
}

17.2 Are there any events that get fired when the user scrolls?

You could override WndProc and listen for (0x114 WM_HSCROLL) and (0x115 WM_VSCROLL)
messages (m.Msg will be set to the above values). These messages should be sent when the user scrolls.

© 2001-06 Copyright George Shepherd.

18. Windows Forms Tips FAQ Home


18.1 How do I write a screen saver?
18.2 How do I determine the screen resolution?
18.3 How do I determine the working area of a screen without the systemtray area?
18.4 How do I position my form to the bottom right of the screen when it opens up the first time above
the system tray?
18.5 How do I change my screen's resolution programatically?
18.6 How do I determine the current date/time?
18.7 How do I determine the time taken for a long operation that I perform?
18.8 What are the implications of using the Timer class in System.Timers as opposed to the Timer class
in System.Windows.Forms?
18.9 Is there an easy way to Create/Delete/Move files in the Windows File System?
18.10 How can I use XP Themes with Windows Forms using the .NET FrameWork 1.1?
18.11 How can I use XP Themes with Windows Forms using the .NET FrameWork 1.0?
18.12 How do I use Windows Forms Controls in Internet Explorer?
18.13 Are event handlers required to have this signature void MyEventHandler(object sender, EventArgs
e)?
18.14 How do I change a directory name?
18.15 How do I beep the computer's speaker in a Windows Form application?
18.16 How do I use the system clipboard?
18.17 How do I add an application to the Window's Tray?
18.18 Why would I be getting a NullReferenceException in Windows Forms with no application code in
the call stack?
18.19 When I try to catch the Resize event to handle sizing of MDI children, the event is called even
before my form's constructor can create the children throwing an exception. How do I avoid this?
18.20 How can I tell if the user has changed some system preference such as the locale or display
settings?
18.21 What mechanisms does .Net provide to convert one type to another?
18.22 Its possible that some of my class members will not be initialized when one of my virtual members
gets called even before the constructor. How can I avoid this?
18.23 In a Hashtable, why doesn't setting the value for an existing key to be null remove the key from the
Hashtable?
18.24 How do I create windows shortcuts on my desktop programatically in .Net?
18.25 How can I add a custom verb to the file and folder context menus in the explorer shell?
18.26 Can working on WinForms and .Net in general get exciting?
18.27 I have a long loop. How can I make my application continue to process events while it is executing
this loop?
18.28 How can I display HTML in a Form?
18.29 The MessageBox always appears in the center of the screen. How can I change it's location?
18.30 If I have a button with &Next as the text, the N-accelerator key does not appear until I press Alt.
Why?
18.31 How can I shut down/restart the OS from my Windows Forms Application?
18.32 I get a message 'DragDrop registration' failed. Why?
18.33 What is the purpose of the [STA Thread] attribute for the Main method of a C# program?
18.34 I add my application to the Window's Tray, set ShowInTaskBar to false, but the program still
appears in the Alt+Tab list.

18.1 How do I write a screen saver?


Check out this sample on gotnetdot.com.

18.2 How do I determine the screen resolution?

Use the System.Windows.Forms.Screen.PrimaryScreen.Bounds property.

18.3 How do I determine the working area of a screen without the systemtray area?

The Screen.GetWorkingArea(control) will provide you the working area of a screen without the system tray
area.

18.4 How do I position my form to the bottom right of the screen when it opens up the first time above the
system tray?

Do as follows in your Form's constructor after setting the StartPosition to Manual:

[C#]
this.SetBounds(Screen.GetWorkingArea(this).Width-this.Width
,Screen.GetWorkingArea(this).Height-this.Height , this.Width, this.Height);

[VB.Net]
Me.SetBounds(Screen.GetWorkingArea(Me).Width-Me.Width
,Screen.GetWorkingArea(Me).Height-Me.Height , Me.Width, Me.Height)

18.5 How do I change my screen's resolution programatically?

You can do so by calling the native ChangeDisplaySetting api.

This website at www.omniscium.com provides you an article on how to do it:


http://www.omniscium.com/index.asp?page=DotNetScreenResolution

18.6 How do I determine the current date/time?

Use the static properties in the DateTime class to get the current date (Today property) and also in terms of
ticks (Ticks property).

18.7 How do I determine the time taken for a long operation that I perform?
You could use the DateTime.Ticks property to record the time taken for a long operation, as follows:

[C#]
private void MyLongOp()
{
long startTicks = DateTime.Now.Ticks;

// Perform a long op:

long endTicks = DateTime.Now.Ticks;

long delta = endTicks - startTicks;


MessageBox.Show("Time taken in Ticks: " + delta.ToString());
delta = delta/(long)10000000; // A tick is 100 nanoseconds
MesaageBox.Show("Time taken in seconds: " + delta.ToString());
}

[VB.Net]
Private Sub MyLongOp()
Dim startTicks As Long = DateTime.Now.Ticks

' Perform a long op:

Dim endTicks As Long = DateTime.Now.Ticks

Dim delta As Long = endTicks - startTicks


MessageBox.Show("Time taken in Ticks: " + delta.ToString())
delta = delta/(Long)10000000 ' A tick is 100 nanoseconds
MesaageBox.Show("Time taken in seconds: " + delta.ToString())
End Sub

18.8 What are the implications of using the Timer class in System.Timers as opposed to the Timer class in
System.Windows.Forms?

Be careful when useing the Timer from System.Timers from within a Windows.Form application. Most
methods in Windows Forms are not thread safe and can produce indeterminate results when called from
another thread. In this case, System.Timers.Timer is much higher resolution and less affected by how busy
your application is (since it doesn't use the message pump) but it's Tick event is fired from another thread.
In order to be sure this works correctly, you'll have to write the proper Control.Invoke code to marshal over
to the thread the control was created on (the main thread) before you call methods on the control. So, in
cases where you don't need super-high-resolution and regular events to be fired, you're much better off
using System.Windows.Forms.Timer. It's messsage pump is based (WM_TIMER) and will fire on the UI
thread.

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

18.9 Is there an easy way to Create/Delete/Move files in the Windows File System?

Use File.Create, Delete and Move static methods.

18.10 How can I use XP Themes with Windows Forms using the .NET FrameWork 1.1?

The .manifest file is not required if you are using .NET FrameWork 1.1. You can now use the application's
EnableVisualStyles() method which should called before creating any controls. You also need to ensure that
the FlatStyle property of the control is changed to System/b> instead of the default value of Standard.

[C#]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}

[VB.Net]
Public Shared Sub Main()

System.Windows.Forms.Application.EnableVisualStyles()
System.Windows.Forms.Application.Run(New Form1)
End Sub

18.11 How can I use XP Themes with Windows Forms using the .NET FrameWork 1.0?

Follow these steps to introduce Windows XP visual styles into your Windows application.

1. Create a new Windows Application and add some controls to the default form.
2. For every control you place on the form that has a FlatStyle property, set the property to System.
3. Compile your application.
4. Build a manifest file in the application directory. NOTE: This manifest file must be located in the same
directory as the executable. Open Notepad and place the code shown below in the file.
.NET control deployment tool

type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>

Save the file in the application directory with the name of the application and an extension of exe.manifest.
For instance, if your application name is "MyApp", you will name the manifest file as
MyApp.exe.manifest.
5. When your application runs, Windows XP looks at the application manifest which tells the operating
system to use common controls library version 6.0.

This process is discussed and a sample given in an article by the David C. Brown on the Windows Forms
team at gotnetdot.com.

18.12 How do I use Windows Forms Controls in Internet Explorer?

Erick Ellis steps you through creating a Windows Form and then adding an object tag to an HTML page in
his article Using Windows Forms Controls in IE on gotnetdot.com.

18.13 Are event handlers required to have this signature void MyEventHandler(object sender, EventArgs
e)?

C#

18.14 How do I change a directory name?

Use the static move member of the Directory class.


Directory.Move(oldPathString, newPathString);

18.15 How do I beep the computer's speaker in a Windows Form application?

There is no Windows Form function to beep your computer's speaker. But you can just invoke the Win32
API MessageBeep.

using System.Runtime.InteropServices;
...

[DllImport("user32.dll")]
public static extern int MessageBeep(uint n);

private void button2_Click(object sender, System.EventArgs e)


{
MessageBeep(0x0);
}

Another method (suggested by msauper@sauper.com on


microsoft.public.dotnet.framework.windowsforms)

Reference the VB.NET runtime support and just use the Beep() method.

The method is in:

Microsoft.Visual Basic.NET Runtime

The method is:

Microsoft.VisualBasic.Interaction.Beep();

18.16 How do I use the system clipboard?

The SetDataObject and GetDataObject methods in the Clipboard class found in the
System.Windows.Forms namespace allows you to access the clipboard. Here is some code.

string text = "Some text for the clipboard";


Clipboard.SetDataObject(text); //clipboard now has "Some text for the clipboard"

text = ""; //zap text so it can be reset...


IDataObject data = Clipboard.GetDataObject();
if(data.GetDataPresent(DataFormats.Text))
{
text = (String)data.GetData(DataFormats.Text);
//text is now back to "Some text for the clipboard"
}

18.17 How do I add an application to the Window's Tray?

In design mode, you drop a NotifyIcon object on your form. You can then drop a ContextMenu on your
form and add this menu to the NotifyIcon's ContextMenu property. This menu will be seen when the user
rightclicks the try icon. You can add a handler for the NotifyIcon's Click event to catch the action of a user
clicking the icon.

From code, you create an instance of NotifyIcon, set properties, hook any handlers you want, and then
make it visible. Here are some VB snippets.

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles


MyBase.Load
Dim trayItem As NotifyIcon = New NotifyIcon()
trayItem.Icon = SystemIcons.Question
trayItem.Visible = True
AddHandler trayItem.Click, New EventHandler(AddressOf HandleTrayClick)
End Sub

Private Sub HandleTrayClick(ByVal sender As Object, ByVal e As EventArgs)


MessageBox.Show("Tray item clicked")
End Sub

18.18 Why would I be getting a NullReferenceException in Windows Forms with no application code in
the call stack?

The CLR is catching an Access Violation that's being thrown from unmanaged code, and that is
propogating up as a NullReferenceException. I've seen this happen with certain common control library
windows types if an application such as spy++ is running, and I see this is the TreeView control that is
having troubles with a mouse down. Have you done any modification to the control through P/Invoke
methods?

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

18.19 When I try to catch the Resize event to handle sizing of MDI children, the event is called even before
my form's constructor can create the children throwing an exception. How do I avoid this?
The Resize event is getting raised before the constructor completes because the form is being resized in the
constructor. If you are using VS.NET to create your project, then in your constructor there is a call to
InitializeComponent. In this method there is code to resize the form. You could instantiate your child form
in your constructor *before* InitializeComponent is called, then when the form gets resized for the first
time you already have an instance of your child form.

(broderonline@microsoft.com_(Brian_Roder))

18.20 How can I tell if the user has changed some system preference such as the locale or display settings?

Use the static events in the SystemEvents class found in the Microsoft.Win32 namespace. There are many
events in this class. Here are a couple:

SystemEvents.DisplaySettingsChanged += new System.EventHandler(displaySettingsChanged);


SystemEvents.UserPreferenceChanged +=
new UserPreferenceChangedEventHandler(userPreferencesChanged);

.............
.............

private void displaySettingsChanged(object sender, EventArgs e)


{
MessageBox.Show(e.ToString());
}

private void userPreferencesChanged(object sender, UserPreferenceChangedEventArgs e)


{
switch(e.Category)
{
case UserPreferenceCategory.Locale:
MessageBox.Show("Changed locale");
break;
default:
MessageBox.Show(e.Category.ToString());
break;
}
}

18.21 What mechanisms does .Net provide to convert one type to another?

Type conversion is usually possible in one of the following ways:

1) Using explicit methods in source type like:

public class SizeF


{
...
public Size ToSize();
}

There is usually a corresponding explicit or implicit operator that does the same conversion. The operators
are however not available in VB.Net.

2) Using FromXXX static methods exposed in the destination type:

class Image
{
...
public static Image FromStream(Stream);
}

3) Using implicit or explicit operators defined in the source or destination type. This will allow you to
perform implicit or explicit casts from the source type to the destination type.

SizeF sizeF = size; // Possible because type Size has an implicit type conversion operator that converts a
Size to SizeF

PointF pointF = (PointF)sizeF; // Possible because type SizeF has an explict type conversion operator
that converts a SizeF to PointF.

There is usually a corresponding ToXXX method that does the same conversion. You can use either this or
the ToXXX methods in C#.

4) Using TypeConverters. Some types come with TypeConverters that allow you to convert to or convert
from another type. This conversion is usually not documented and can be discovered only by writing some
test code.

For example, the System.Drawing.Icon type's TypeConverter converts the Icon into a byte[]. You can use
this functionality in your code as follows:

TypeConverter tc = TypeDescriptor.GetConverter(typeof(System.Drawing.Icon));
byte[] blob = tc.ConvertTo(myIcon, typeof(byte[]));

It's usually time consuming to figure out whether a TypeConverter's ConvertTo or ConvertFrom method
can perform the necessary conversion.

The attached TypeConverterLookup tool lets you figure that out easily on any type declared in any
assembly available in the GAC or available in the same directory as the tool's exe. If you have types in
custom assemblies, then just copy over that assembly to the same directory as the tool, you can then specify
the type in the tool.
18.22 Its possible that some of my class members will not be initialized when one of my virtual members
gets called even before the constructor. How can I avoid this?

If possible, initialize them in-line:

public class MyClass


{
public ArrayList myArrayList = new ArrayList();

public MyClass(){}

public override void MyOverride()


{
// When this gets called by the base class construcotr, myArrayList will be initialized.
}

18.23 In a Hashtable, why doesn't setting the value for an existing key to be null remove the key from the
Hashtable?

This is by design. You have to use Remove to actually remove the Key/Value pair from the Hashtable.

18.24 How do I create windows shortcuts on my desktop programatically in .Net?

The following article explains how shortcuts can be created programatically: Creating and Modifying
Shortcuts

18.25 How can I add a custom verb to the file and folder context menus in the explorer shell?

The article at www.vbaccelerator.com shows you how it is done in .net: Associating Applications with Any
File or Folder

18.26 Can working on WinForms and .Net in general get exciting?

Yes, only if you work at Syncfusion, Inc.

18.27 I have a long loop. How can I make my application continue to process events while it is executing
this loop?
Call the static Application.DoEvents() method in your loop.

18.28 How can I display HTML in a Form?

You can add a web browser to a form in a straight forward manner.


1) Right-click your toolbox and select Customize Toolbox. Then add the Com Component 'Microsoft Web
Browser'.
2) Drag the just added Explorer tool and drop it on your form to position it where you want it.
3) Set the inital display page using code such as:

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

object a = 0;
object b = 0;
object c = 0;
object d = 0;
axWebBrowser1.Navigate("www.syncfusion.com", ref a, ref b, ref c, ref d);

//
// TODO: Add any constructor code after InitializeComponent call
//
}

18.29 The MessageBox always appears in the center of the screen. How can I change it's location?

Its looks like you cannot change this behavior of MessageBox. One solution is to derive your own
MessageForm class from Form to display your message. Then call its ShowDialog method to show it after
you set its Size, Location and StartPosition properties. (If you don't set the StartPosition , then the Location
is ignored.) One of the values for StartPosition is CenterParent which would center your new
MessageForm.

18.30 If I have a button with &Next as the text, the N-accelerator key does not appear until I press Alt.
Why?

This behavior has nothing to do with .Net and is expected Windows behavior beginning with Win2000.
Windows will only show accelerator keys after the alt is pressed. There is a control panel setting that you
can use to change this behavior. Look on the Effects tab under Control Panel|Display to see a checkbox
labeled "Hide keyboard navigation indicators until I use the Alt key".
18.31 How can I shut down/restart the OS from my Windows Forms Application?

You could do this using the WMI Classes in the .NET Framework or use WindowsController available at
http://www.mentalis.org

18.32 I get a message 'DragDrop registration' failed. Why?

Try placing the attribute [STA Thread] on your Main method. OLE D&D requires single threaded
apartments.

[STAThread]
static void Main()
{
Application.Run(new Form1());
}

18.33 What is the purpose of the [STA Thread] attribute for the Main method of a C# program?

That marks the thread as being "Single Thread Apartment" which means any multiple threaded calls need to
be marshaled over to that thread before they are called. That's there because Windows Forms uses some
OLE calls (Clipboard for example), which must be made from the thread that initialized OLE.

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

18.34 I add my application to the Window's Tray, set ShowInTaskBar to false, but the program still appears
in the Alt+Tab list.

An easy way to keep the program from appearing in the Alt+Tab list is to set the Form's FormBorderStyle
property to be a ToolWindow (fixed or sizable).

One caveat to this is that if you display another Form (that is not a ToolWindow) through a call in your
application, the main Form will again appear in the Alt+Tab listing. To get around this, you can make all of
the Forms in your Tray application have a FormBorderStyle of ToolWindow.
© 2001-06 Copyright George Shepherd.

19. Windows Forms Common Dialogs FAQ Home


19.1 How do I use the ColorDialog to pick a color?
19.2 How do I use the FontDialog class to set a control's font?
19.3 How do I implement a Folder Browser class?
19.4 How can I get just the name of a file from the complete path string?
19.5 How can I get just the extension of a file from the complete path string?
19.6 How do I use the OpenFileDialog?
19.7 How do I specify the path for the FolderBrowser instance when it opens the first time?

19.1 How do I use the ColorDialog to pick a color?

It is straight-forward. Create an instance of the class and call its ShowDialog method.

ColorDialog colorDialog1 = new ColorDialog();


//fontDialog1.ShowColor = true;
if(colorDialog1.ShowDialog() != DialogResult.Cancel )
{
textBox1.ForeColor = colorDialog1.Color;
}
textBox1.Text = "this is a test";

19.2 How do I use the FontDialog class to set a control's font?

It is straight-forward. Create an instance of the class and call its ShowDialog method.

FontDialog fontDialog1 = new FontDialog();


fontDialog1.ShowColor = true;
if(fontDialog1.ShowDialog() != DialogResult.Cancel )
{
textBox1.Font = fontDialog1.Font ;
textBox1.ForeColor = fontDialog1.Color;
}

textBox1.Text = "this is a test";

19.3 How do I implement a Folder Browser class?


Below is a technique that uses FolderNameEditor and FolderBrowser classes to implement a solution. You
can also use iterop to get a solution.
Both the FolderNameEditor and FolderBrowser classes used in this solution are described in the Docs as
"This type supports the .NET Framework infrastructure and is not intended to be used directly from your
code."

// add a reference to System.Design.DLL

using System.Windows.Forms.Design;
.............

public class DirBrowser : FolderNameEditor


{
FolderBrowser fb = new FolderBrowser();

public string Description


{
set { _description = value; }
get { return _description; }
}

public string ReturnPath


{
get { return _returnPath; }
}

public DirBrowser() { }

public DialogResult ShowDialog()


{
fb.Description = _description;
fb.StartLocation = FolderBrowserFolder.MyComputer;

DialogResult r = fb.ShowDialog();
if (r == DialogResult.OK)
_returnPath = fb.DirectoryPath;
else
_returnPath = String.Empty;

return r;
}

private string _description = "Choose Directory";


private string _returnPath = String.Empty;
}

(Posted by Ryan Farley on the microsoft.public.dotnet.language.csharp newsgroup)

19.4 How can I get just the name of a file from the complete path string?
Use FileInfo. Instantiate a FileInfo object with the full path as constructor arg. Then simply call
FileInfo.Name and you will get just the name of the file.

FileInfo finfo = new FileInfo(strFileName);


Console.WriteLine(finfo.Name);

19.5 How can I get just the extension of a file from the complete path string?

Use FileInfo. Instantiate a FileInfo object with the full path as constructor arg. Then simply call
FileInfo.Extension and you will get just the extension of the file.

FileInfo finfo = new FileInfo(strFileName);


Console.WriteLine(finfo.Extension);

19.6 How do I use the OpenFileDialog?

using System.Text;
using System.IO;
....
private void button1_Click(object sender, System.EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "Open text file" ;
dlg.InitialDirectory = @"c:\" ;
dlg.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" ;

if(dlg.ShowDialog() == DialogResult.OK)
{
StreamReader sr = File.OpenText(dlg.FileName);

string s = sr.ReadLine();
StringBuilder sb = new StringBuilder();
while (s != null)
{
sb.Append(s);
s = sr.ReadLine();
}
sr.Close();
textBox1.Text = sb.ToString();
}
}
19.7 How do I specify the path for the FolderBrowser instance when it opens the first time?

In the 1.1 framework there is a SelectedPath property that will let you do this.

© 2001-06 Copyright George Shepherd.

20. Windows Forms ListBox FAQ Home


20.1 How do I add and delete items from a ListBox?
20.2 How do I implement Drag and Drop support between ListBoxes?
20.3 How can I drag file names from Windows Explorer and drop them into a listbox?
20.4 How do I implement an ownerdrawn listbox?
20.5 How can I set the width of a listbox to fit the text?

20.1 How do I add and delete items from a ListBox?

Check out Devinder Arora's article Using ListBox Control in C# on C# Corner.

20.2 How do I implement Drag and Drop support between ListBoxes?

The code below minimally handles D&D for a single selection list box by handling four events. The D&D
is initiated in MouseDown if the user mouses down on the current selection. The DragEnter event is used to
set the dragging effect to copy if you are not over the drag source. The DragDrop event is used to do the
drop. And finally, the SelectedIndexChanged event is used to track the current selection for use in the
MouseDown event. You can download a working project (C#, VB). This project handles additional events
to provide visual queues during the drop.

The samples referenced above do not allow dragging and dropping within the same listbox. Here is another
set of samples that does allow you to drag and drop within the same listbox.

public class ListBoxDragNDrop : ListBox


{
private int lastMouseUpItemIndex = -1;
private bool isDropSource = false;
public ListBoxDragNDrop()
{
this.AllowDrop = true; //allow D&D
this.SelectionMode = SelectionMode.One; //single selection

DragDrop += new System.Windows.Forms.DragEventHandler(OnDragDrop);


DragEnter += new System.Windows.Forms.DragEventHandler(OnDragEnter);
MouseDown += new System.Windows.Forms.MouseEventHandler(OnMouseDown);
SelectedIndexChanged += new System.EventHandler(OnSelectedIndexChanged);
}

private void OnDragDrop(object sender, DragEventArgs e)


{
if(e.Effect == DragDropEffects.Copy)
{
Point point = this.PointToClient(new Point(e.X, e.Y));
int index = this.IndexFromPoint(point);
if( index > -1 && index < this.Items.Count)
Items.Insert(index, e.Data.GetData(DataFormats.Text));
else
Items.Add(e.Data.GetData(DataFormats.Text));
}
}

private void OnDragEnter(object sender, System.Windows.Forms.DragEventArgs e)


{
if (e.Data.GetDataPresent(DataFormats.Text) && !isDropSource )
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
}

private void OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)


{
if(MouseButtons == MouseButtons.Left && SelectedIndex == lastMouseUpItemIndex)
{
isDropSource = true;
DoDragDrop(SelectedItem, DragDropEffects.Copy);
isDropSource = false;
lastMouseUpItemIndex = this.SelectedIndex;
}
}

private void OnSelectedIndexChanged(object sender, System.EventArgs e)


{
lastMouseUpItemIndex = this.SelectedIndex;
}
}
One more note. If your listboxes contain full file pathnames, you can support dropping these paths onto
Windows Explorer by supporting the FileDrop dataformat. In the OnMouseDown override, if you replace
the DoDragDrop line with the following code block, you will be able to drop files.

//put the file path is a string array


string[] files = new String[1];
files[0] = SelectedItem.ToString();

//create a dataobject holding this array as a filedrop


DataObject data = new DataObject(DataFormats.FileDrop, files);

//also add the selection as textdata


data.SetData(DataFormats.StringFormat, SelectedItem.ToString());

//do the dragdrop


DoDragDrop(data, DragDropEffects.Copy);

20.3 How can I drag file names from Windows Explorer and drop them into a listbox?

Place a ListBox on your form, set its AllowDrop property and handle both DragEnter and DragDrop as
below.

private void listBox1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)


{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.All;
else
e.Effect = DragDropEffects.None;
}

private void listBox1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)


{
string[] files = (string[])e.Data.GetData("FileDrop", false);
foreach (string s in files)
{
//just filename
listBox1.Items.Add(s.Substring(1 + s.LastIndexOf(@"\")));

//or fullpathname
// listBox1.Items.Add(s);
}
}

Here are some VB snippets.

Private Sub listBox1_DragEnter(sender As Object, e As System.Windows.Forms.DragEventArgs)


If e.Data.GetDataPresent(DataFormats.FileDrop) Then
e.Effect = DragDropEffects.All
Else
e.Effect = DragDropEffects.None
End If

End Sub 'listBox1_DragEnter

Private Sub listBox1_DragDrop(sender As Object, e As System.Windows.Forms.DragEventArgs)

Dim files As String() = CType(e.Data.GetData("FileDrop", False), String())


Dim s As String
For Each s In files
'just filename
listBox1.Items.Add(s.Substring(1 + s.LastIndexOf("\")))

or fullpathname
' listBox1.Items.Add(s)
Next s

End Sub 'listBox1_DragDrop

20.4 How do I implement an ownerdrawn listbox?

Check out this sample project at gotnetdot.com. It derives from Form and implements the owner drawing
by handling the DrawItem event and MeasureItem event.

You can also download a sample that implements an owner drawn listbox by deriving from ListBox and
overriding the virtual methods OnDrawItem and OnMeasureItem. Here is a OnDrawItem override that
draws colored rectangles in the listbox.

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)


{
//undo the selection rect on the old selection
if( oldSelectedRect != e.Bounds &&
oldSelectedIndex > -1 && oldSelectedIndex < Items.Count)
{
e.Graphics.DrawRectangle(new Pen((Color) Items[oldSelectedIndex], 2), oldSelectedRect);
}

//draw the item .. here we just fill a rect


if( e.Index > -1 && e.Index < Items.Count)
e.Graphics.FillRectangle(new SolidBrush( (Color)Items[e.Index] ), e.Bounds);

//draw selection rect if needed


if(SelectedIndex == e.Index)
{
e.Graphics.DrawRectangle(new Pen(Color.Black,2), e.Bounds);
oldSelectedRect = e.Bounds;
oldSelectedIndex = e.Index;
}
}

20.5 How can I set the width of a listbox to fit the text?

You can iterate through the list to find the longest text extent using MeasureString, adding a fudge factor if
the is present.

System.Drawing.Graphics g = listBox1.CreateGraphics();
float maxWidth = 0f;
float height = 0f;

for(int i = 0; i < listBox1.Items.Count; ++i)


{
float w = g.MeasureString(listBox1.Items[i].ToString(), listBox1.Font).Width;
if(w > maxWidth)
maxWidth = w;
height += listBox1.GetItemHeight(i);
}
g.Dispose();

listBox1.Width = (int) (maxWidth + 6 + ((height > listBox1.Height - 4) ? 16 : 0)); // 16 is scrollbar


width

© 2001-06 Copyright George Shepherd.

21. Windows Forms ComboBox FAQ Home


21.1 How do I bind the values of an enum to a ComboBox?
21.2 How can I programmatically prevent the combobox from dropping?
21.3 How can I turn off editing in the textbox portion of a ComboBox, restricting the user to selecting
only those options in the drop list?
21.4 How can I adjust the height of the of my ComboBox dropdown?
21.5 How do I implement an owner drawn combobox?
21.6 How do I add a ComboBox button to a toolbar?
21.7 How do I set the width of a combobox to fit the entries in its list?
21.8 How can I programmatically create a new list for my ComboBox dropdown?

21.1 How do I bind the values of an enum to a ComboBox?

This entry was created using the feedback provided by Jay Harlow in the newsgroups.

The enum values can be bound to a combobox as follows:

[C#]
// Setup the binding as follows:
// MyValues is the enum type
comboBox1.DataSource = Enum.GetValues(typeof MyValues);
[VB]
comboBox1.DataSource = Enum.GetValues(Type.GetType(MyValues))

Then in the SelectedValueChanged event for the ComboBox.

[C#]
private void ComboBox1ValueChanged(object sender, EventArgs e)
{
MyValues v = (MyValues)this.comboBox1.SelectedValue;
}
[VB]
Private Sub ComboBox1ValueChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim v As MyValues = CType(Me.comboBox1.SelectedValue, MyValues)
End Sub

21.2 How can I programmatically prevent the combobox from dropping?

You can avoid the combobox dropping by overriding its WndProc method and ignoring the
WM_LBUTTONDOWN and WM_LBUTTONDBLCLK.

[C#]
public class MyComboBox : ComboBox
{
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if(m.Msg == 0x201 //WM_LBUTTONDOWN
|| m.Msg == 0x203) //WM_LBUTTONDBLCLK
return;
base.WndProc(ref m);
}
}

[VB.NET]
Public Class MyComboBox
Inherits ComboBox

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)


If m.Msg = &H201 OrElse m.Msg = &H203 Then 'WM_LBUTTONDOWN or
WM_LBUTTONDBLCLK
Return
End If

MyBase.WndProc(m)
End Sub 'WndProc
End Class 'MyComboBox

21.3 How can I turn off editing in the textbox portion of a ComboBox, restricting the user to selecting only
those options in the drop list?

Set the combobox's DropDownStyle property to DropDownList .

21.4 How can I adjust the height of the of my ComboBox dropdown?

You can control the height by changing the value of the MaxDropDownItems property of the the
Combobox, which is the setting for maximum number of entries that will be displayed by the drop-down
list.

21.5 How do I implement an owner drawn combobox?

You can subclass ComboBox. In your derived class, make sure you set

this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.DropDownStyle = ComboBoxStyle.DropDownList;

You also need to handle the DrawItem event to actually implement the drawing. Check out the details in the
OwnerDrawnComboBox sample.
21.6 How do I add a ComboBox button to a toolbar?

Michael Gold discusses this problem in How to create a ComboBox button in a toolbar in .NET on C#
Corner.

21.7 How do I set the width of a combobox to fit the entries in its list?

You can iterate through the list to find the longest text extent using MeasureString, and then use this as the
combobox width adding a fudge factor for the dropdown button.

System.Drawing.Graphics g = comboBox1.CreateGraphics();
float maxWidth = 0f;
foreach(object o in comboBox1.Items)
{
float w = g.MeasureString(o.ToString(), comboBox1.Font).Width;
if(w > maxWidth)
maxWidth = w;
}
g.Dispose();
comboBox1.Width = (int) maxWidth + 20; // 20 is to take care of button width

21.8 How can I programmatically create a new list for my ComboBox dropdown?

Here are some snippets. (Courtesy of Michael Lang)

[C#]
DataTable list = new DataTable();
list.Columns.Add(new DataColumn("Display", typeof(string)));
list.Columns.Add(new DataColumn("Id", typeof(int)));
list.Rows.Add(list.NewRow());
list.Rows.Add(list.NewRow());
list.Rows.Add(list.NewRow());
list.Rows[0][0] = "one";
list.Rows[0][1] = 1;
list.Rows[1][0] = "two";
list.Rows[1][1] = 2;
list.Rows[2][0] = "three";
list.Rows[2][1] = 3;
comboBox1.DataSource = list;
comboBox1.DisplayMember = "Display";
comboBox1.ValueMember = "Id";

[VB.NET]
Dim list As New DataTable()
list.Columns.Add(New DataColumn("Display", GetType(String)))
list.Columns.Add(New DataColumn("Id", GetType(Integer)))
list.Rows.Add(list.NewRow())
list.Rows.Add(list.NewRow())
list.Rows.Add(list.NewRow())
list.Rows(0)(0) = "one" '
list.Rows(0)(1) = 1 '
list.Rows(1)(0) = "two" '
list.Rows(1)(1) = 2 '
list.Rows(2)(0) = "three" '
list.Rows(2)(1) = 3 '
comboBox1.DataSource = list
comboBox1.DisplayMember = "Display"
comboBox1.ValueMember = "Id"

© 2001-06 Copyright George Shepherd.

22. Windows Forms RichTextBox FAQ Home


22.1 How can I create and save a RTF file?
22.2 How can I get a string that contains RTF format codes into a RichTextBox?
22.3 How do I make the RichTextBox support drag and drop?
22.4 How do I set the color and font in a RichEditBox?
22.5 How can I change the FontStyle of a selection without losing the styles that are present?
22.6 How can I programmatically position the cursor on a given line and character of my richtextbox?
22.7 How can I load an embedded rich text file into a richtextbox?
22.8 How can I print my rich text?
22.9 Where can I find more information on the RTF specification?
22.10 How can I add a hyperlink to a RichTextBox control?

22.1 How can I create and save a RTF file?


One way to do this is to use the RichTextBox.SaveFile method.

private void button1_Click(object sender, System.EventArgs e)


{
// Create a SaveFileDialog & initialize the RTF extension
SaveFileDialog saveFile1 = new SaveFileDialog();
saveFile1.DefaultExt = "*.rtf";
saveFile1.Filter = "RTF Files|*.rtf";

// get a file name from the user


if(saveFile1.ShowDialog() == DialogResult.OK)
{
// Save the RTF contents of the RichTextBox control that
// was dragged onto the Window Form and populated somehow
richTextBox1.SaveFile(saveFile1.FileName,
RichTextBoxStreamType.RichText); //use to save RTF tags in file
//RichTextBoxStreamType.PlainText);//use to save plain text in file
}
}

22.2 How can I get a string that contains RTF format codes into a RichTextBox?

Use the Rtf property of the control.

richTextBox1.Rtf = @"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fswiss\fcharset0
Arial;}}\viewkind4\uc1\pard\b\i\f0\fs20 This is bold italics.\par }";

22.3 How do I make the RichTextBox support drag and drop?

1) Set the AllowDrop property to true


2) Add handlers for both the DragEnter and DragDrop event

this.richTextBox1.DragEnter += new
System.Windows.Forms.DragEventHandler(this.richTextBox1_DragEnter);
this.richTextBox1.DragDrop += new
System.Windows.Forms.DragEventHandler(this.richTextBox1_DragEnter);

....

private void richTextBox1_DragEnter(object sender,


System.Windows.Forms.DragEventArgs e)
{
if (((DragEventArgs)e).Data.GetDataPresent(DataFormats.Text))
((DragEventArgs)e).Effect = DragDropEffects.Copy;
else
((DragEventArgs)e).Effect = DragDropEffects.None;
}

private void richTextBox1_DragDrop(object sender, DragEventArgs e)


{
// Loads the file into the control.
richTextBox1.LoadFile((String)e.Data.GetData("Text"),
System.Windows.Forms.RichTextBoxStreamType.RichText);
}

Here are VB snippets.

AddHandler Me.richTextBox1.DragEnter, New System.Windows.Forms.DragEventHandler(AddressOf


Me.richTextBox1_DragEnter)
AddHandler Me.richTextBox1.DragDrop, New System.Windows.Forms.DragEventHandler(AddressOf
Me.richTextBox1_DragEnter)

.....

Private Sub richTextBox1_DragEnter(sender As Object, e As System.Windows.Forms.DragEventArgs)

If CType(e, DragEventArgs).Data.GetDataPresent(DataFormats.Text) Then


CType(e, DragEventArgs).Effect = DragDropEffects.Copy
Else
CType(e, DragEventArgs).Effect = DragDropEffects.None
End If

End Sub 'richTextBox1_DragEnter

Private Sub richTextBox1_DragDrop(sender As Object, e As DragEventArgs)

' Loads the file into the control.


richTextBox1.LoadFile(CType(e.Data.GetData("Text"), [String]),
System.Windows.Forms.RichTextBoxStreamType.RichText)

End Sub 'richTextBox1_DragDrop

22.4 How do I set the color and font in a RichEditBox?

You use the SelectionFont and SelectionColor properties. Make sure the control had focus. Then the
following code will set the currently selected text to a red-bold-courier font. If no text is currently selected,
then any new text typed (or inserted) will be red-bold-courier.
[C#]
richTextBox1.Focus();
richTextBox1.SelectionColor = Color.Red;
richTextBox1.SelectionFont = new Font ("Courier", 10, FontStyle.Bold);

[VB.NET]
richTextBox1.Focus()
richTextBox1.SelectionColor = Color.Red
richTextBox1.SelectionFont = new Font ("Courier", 10, FontStyle.Bold)

22.5 How can I change the FontStyle of a selection without losing the styles that are present?

If you visit the selection a character at the time, you can get the current FontStyle and modify it directly to
add or remove a style like Bold or Italic. Doing it a character at a time will avoid losing the other styles that
are set. The problem with doing it a whole selection at a time is that the FontStyle of the entire selection is
the common styles set among all characters in the selection. So, if one char is bold and one is not, then bold
is not set when you retrieve the fontstyle for the entire selection. Doing things a character at the time,
avoids this problem and allows things to work OK. You can download a working sample(CS,VB).

private void AddFontStyle(FontStyle style)


{
int start = richTextBox1.SelectionStart;
int len = richTextBox1.SelectionLength;
System.Drawing.Font currentFont;
FontStyle fs;
for(int i = 0; i < len; ++i)
{
richTextBox1.Select(start + i, 1);
currentFont = richTextBox1.SelectionFont;
fs = currentFont.Style;
//add style
fs = fs | style;
richTextBox1.SelectionFont = new Font(
currentFont.FontFamily,
currentFont.Size,
fs
);
}
}

private void RemoveFontStyle(FontStyle style)


{
int start = richTextBox1.SelectionStart;
int len = richTextBox1.SelectionLength;
System.Drawing.Font currentFont;
FontStyle fs;
for(int i = 0; i < len; ++i)
{
richTextBox1.Select(start + i, 1);
currentFont = richTextBox1.SelectionFont;
fs = currentFont.Style;
//remove style
fs = fs & ~style;
richTextBox1.SelectionFont = new Font(
currentFont.FontFamily,
currentFont.Size,
fs
);
}
}

private void button1_Click(object sender, System.EventArgs e)


{
AddFontStyle(FontStyle.Bold);
}

Here is a suggestion from Nicholas Clark on how to avoid seeing the character by character changes appear
as you apply the styles one character at a time in the above code. Create a hidden RTB and store the
selected text in it. Then apply the attributes and copy it back into the original richtextbox, so that you don't
see the selection changing.

private void change_font(FontStyle style,bool add)


{
richTextBox2.Rtf = richTextBox1.SelectedRtf;
int lengt = richTextBox2.Text.Length;
int length = richTextBox1.SelectionLength;
int start = richTextBox1.SelectionStart;
for (int i = 0; i < lengt; i++) {
richTextBox2.Select(i,1);
Font cfont = richTextBox2.SelectionFont;
FontStyle fs = cfont.Style;
if (add) {
fs = fs | style;
}
else {
fs = fs & ~style;
}
richTextBox2.SelectionFont = new Font(
cfont.FontFamily,
cfont.Size,
fs
);
}
richTextBox2.Select(0,richTextBox2.Text.Length);
richTextBox1.SelectedRtf = richTextBox2.SelectedRtf;
richTextBox1.Select(start,length);
this.richTextBox1.Focus();
isChanged = true;
}

22.6 How can I programmatically position the cursor on a given line and character of my richtextbox?

There are a couple different methods that can be used here. The first changes focus, so may not be possible
if you have controls that fire validation. The second uses interop, which requires full trust.
Method 1: Eric Terrell suggested this solution in an email to winformsfaq@syncfusion.com.

The richtextbox control contains a Lines array property, one entry for every line. Each line entry has a
Length property. With this information, you can position the selection cursor using code such as:

private void GoToLineAndColumn(RichTextBox RTB, int Line, int Column)


{
int offset = 0;
for (int i = 0; i < Line - 1 && i < RTB.Lines.Length; i++)
{
offset += RTB.Lines[i].Length + 1;
}
RTB.Focus();
RTB.Select(offset + Column, 0);
}

(Note: you may want to store this.ActiveControl to be retrieved after calling Select()).
Method 2:

const int SB_VERT = 1;


const int EM_SETSCROLLPOS = 0x0400 + 222;

[DllImport("user32", CharSet=CharSet.Auto)]
public static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos);

[DllImport("user32", CharSet=CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, POINT lParam);

[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;

public POINT()
{
}

public POINT(int x, int y)


{
this.x = x;
this.y = y;
}
}

// Example -- scroll the RTB so the bottom of the text is always visible.
int min, max;
GetScrollRange(richTextBox1.Handle, SB_VERT, out min, out max);
SendMessage(richTextBox1.Handle, EM_SETSCROLLPOS, 0, new POINT(0, max -
richTextBox1.Height));

22.7 How can I load an embedded rich text file into a richtextbox?

You use the LoadFile method of the RichTextBox, passing it a streamreader based on the resource. So
include your RTF file as an embedded resource in your project, say RTFText.rtf. Then load your
richtextbox with code such as

Stream stream = this.GetType().Assembly.GetManifestResourceStream("MyNameSpace.RTFText.rtf");


if (stream != null)
{
StreamReader sr = new StreamReader(stream);
richTextBox1.LoadFile(stream, RichTextBoxStreamType.RichText);
sr.Close();
}

Here is a VB snippet. Depending on your default namespace settings, you may not need explicit reference
to the namespace in the GetManifestResourceStream argument.

Dim stream As Stream =


Me.GetType().Assembly.GetManifestResourceStream("MyNameSpace.RTFText.rtf")
If Not (stream Is Nothing) Then
Dim sr As New StreamReader(stream)
richTextBox1.LoadFile(stream, RichTextBoxStreamType.RichText)
sr.Close()
End If

22.8 How can I print my rich text?


There is no direct support for printing rich text in the .NET Framework. To print it, you can use interop
with the SendMessage API and these three messages to do your printing.

EM_SETTARGETDEVICE : specify the target device


EM_FORMATRANGE : format part of a rich edit control's contents for a specific device
EM_DISPLAYBAND : send the output to the device

Here is a link to a MSDN article by Martin Muller that implements this interop solution. Getting
WYSIWYG Print Results from a .NET RichTextBox

22.9 Where can I find more information on the RTF specification?

This site has a lot of good information on the RTF specification: http://www.dubois.ws/software/RTF/.

22.10 How can I add a hyperlink to a RichTextBox control?

To add a hyperlink to the RichTextBox, so that it opens up the link you click on, ensure that DetectUrls
property is set to True and call:

[C#]
private void richTextBox1_LinkClicked(object sender, System.Windows.Forms.LinkClickedEventArgs e)
{
System.Diagnostics.Process.Start(e.LinkText);
}

[VB.NET]
Private Sub richTextBox1_LinkClicked(ByVal sender As Object, ByVal e As
System.Windows.Forms.LinkClickedEventArgs)
System.Diagnostics.Process.Start(e.LinkText)
End Sub

© 2001-06 Copyright George Shepherd.


23. Windows Forms ListView FAQ Home
23.1 How do I add SubItems to a ListView control?
23.2 When I call ListViewItem.Selected = true;, why doesn't the item get selected?
23.3 How do I unselect the selected items in a ListView programatically?
23.4 I am trying to programmatically change the ForeColor and BackColor properties of subitems in a
listview. Why doesn't this work?
23.5 How do I implement custom column sorting in a listview?
23.6 How do I programmatically select an item in my listview?
23.7 How can I sort a column in a ListView?
23.8 How can I implement an owner drawn listview?
23.9 How can I tell which column (subitem) has been clicked on in my listview?

23.1 How do I add SubItems to a ListView control?

Try code such as:

ListViewItem item = new ListViewItem("NewItem");


item.SubItems.AddRange(new string[]{"SubItem1", "SubItem2")};
listView1.Items.Add(item);
listView1.Items.Add(new ListViewItem(new string[]{"item1", "item2", "item3", "item4"});
listView1.View = View.Details;

23.2 When I call ListViewItem.Selected = true;, why doesn't the item get selected?

Make sure the ListView has focus when you set the Selected property. For example, if this code is in the
click handler for a button, this button will have the focus, and the selection in the list will fail. Just set the
focus back to the list before you set the Selected property.

23.3 How do I unselect the selected items in a ListView programatically?

Simply do the following:

this.listView1.SelectedItems.Clear();
[C#]

[VB]
Me.listView1.SelectedItems.Clear()
23.4 I am trying to programmatically change the ForeColor and BackColor properties of subitems in a
listview. Why doesn't this work?

Make sure the item's UseItemStyleForSubItems property is set to false.

ListViewItem item1 = new ListViewItem("item1",0);


//this line makes things work
item1.UseItemStyleForSubItems = false;

//set fore & back color of next sub item


item1.SubItems.Add("1", Color.Black, Color.LightGreen, Font);

item1.SubItems.Add("44");
item1.SubItems.Add("3");

//As long as UseItemStyleForSubItems is false, you can later set the colors with code such as
item1.SubItems[2].BackColor = Color.Pink;

23.5 How do I implement custom column sorting in a listview?

You ceate a class the implements the IComparer inteface. This interface has a single method that accepts
two objects, and returns positive integers if the first object is larger than the second, negative integers if the
first object is less than the second object, and returns zero if they are the same. Once you have this class,
then you handle the listview's ColumnClick event to set the property ListViewItemSorter to point to an
instance of this class. You can download a sample project. Here are some snippets.

public class SorterClass : IComparer


{
private int _colNum = 0;
public SorterClass(int colNum)
{
_colNum = colNum;
}

//this routine should return -1 if xy and 0 if x==y.


// for our sample we'll just use string comparison
public int Compare(object x, object y)
{
System.Windows.Forms.ListViewItem item1 = (System.Windows.Forms.ListViewItem) x;
System.Windows.Forms.ListViewItem item2 = (System.Windows.Forms.ListViewItem) y;
if(int.Parse(item1.SubItems[_colNum].Text) < int.Parse(item2.SubItems[_colNum].Text))
return -1;
else if(int.Parse(item1.SubItems[_colNum].Text) > int.Parse(item2.SubItems[_colNum].Text))
return 1;
else
return 0;
}
}

//usage...
private void listView1_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e)
{
//don't sort col 0
if(e.Column > 0)
{
SorterClass sc = new SorterClass(e.Column);
listView1.ListViewItemSorter = sc;
}
}

23.6 How do I programmatically select an item in my listview?

To select the i-th item, you can use code such as

//Make sure the listview has focus


listView1.Focus();
listView1.Items[i].Selected = true;

23.7 How can I sort a column in a ListView?

This Microsoft KB article provides a step by step sample.

23.8 How can I implement an owner drawn listview?

Carlos Perez explains how to do this in an article and a sample on codeproject.com. In this sample, he does
an owner-drawn listview so he can implement custom sorting with a column header that contains a
up/down icon to indicate the sorted column and order.

23.9 How can I tell which column (subitem) has been clicked on in my listview?

Here is a solution offered by Bharat Patel of Microsoft in the microsoft.public.dotnet.languages.csharp


newgroup. The attached solution contains both C# and VB.NET projects. The solution use Interop with the
LVM_GETSUBITEMRECT window's message to loop through each subitem's bounds rectangle until it
finds the one that contains the specified mouse click point.
© 2001-06 Copyright George Shepherd.

24. Windows Forms TreeView FAQ Home


24.1 How do I implement Drag and Drop support between two TreeViews?
24.2 How do I make the TreeView scroll when I drag an item to the top or bottom?
24.3 How do I display checkboxes in the nodes of a treeview?
24.4 When I right-click a tree node, it does not become selected. How can I make it be selected on a
right-click?
24.5 When I get the SelectedNode in the treeview's Click event, it is the old selection. How do I get the
newly selected node?
24.6 How can I get a tooltip to vary from node to node in my treeview?
24.7 How can I determine the node level of a node in my treeview?
24.8 How can I populate a TreeView Control with XML Data?
24.9 How can I clone/copy all the nodes from one TreeView Control to another?
24.10 How do I programmatically select a node in a TreeView control?
24.11 Can I select multiple nodes in a TreeView Control?
24.12 How can I display a context menu when the user right-clicks on a node in the TreeView control?
24.13 How can I ensure that a node is selected when the user clicks along the line of a node?

24.1 How do I implement Drag and Drop support between two TreeViews?

In a posting in the Microsoft.Windows.Forms newsgroup, Brian Roder (Microsoft) gives VB.Net code
snippets to handle the DragEnter, ItemDrag and DragDrop events that provide a solution to this problem.
You can get C# code in this sample, TreeViewDnD. Here is some sample handlers.

private void treeView2_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)


{
TreeNode newNode;
if( e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
{
Point pt;
TreeNode destinationNode;
pt = treeView2.PointToClient(new Point(e.X, e.Y));
destinationNode = treeView2.GetNodeAt(pt);
newNode = (TreeNode) e.Data.GetData("System.Windows.Forms.TreeNode");
if(!destinationNode.Equals(newNode))
{
//destinationNode.Nodes.Add(newNode.Clone());
destinationNode.Nodes.Add((TreeNode) newNode.Clone());
destinationNode.Expand();
//Remove original node
newNode.Remove();
}
}
}

private void treeView2_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)


{
e.Effect = DragDropEffects.Move;
}

private void treeView2_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)


{
DoDragDrop(e.Item, DragDropEffects.Move);
}

24.2 How do I make the TreeView scroll when I drag an item to the top or bottom?

When you drag an item within the TreeView, you can handle the DragOver event for a drag-drop. If you
want to drag-drop into a spot that's not currently visible, you can scroll the TreeView by handling the
DragOver event:

[C#]
private void treeView1_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
{
TreeView tv = sender as TreeView;
Point pt = tv.PointToClient(new Point(e.X,e.Y));

int delta = tv.Height - pt.Y;


if ((delta < tv.Height / 2) && (delta > 0))
{
TreeNode tn = tv.GetNodeAt(pt.X, pt.Y);
if (tn.NextVisibleNode != null)
tn.NextVisibleNode.EnsureVisible();
}
if ((delta > tv.Height / 2) && (delta < tv.Height))
{
TreeNode tn = tv.GetNodeAt(pt.X, pt.Y);
if (tn.PrevVisibleNode != null)
tn.PrevVisibleNode.EnsureVisible();
}
}

[VB.NET]
Private Sub treeView1_DragOver(sender As Object, e As System.Windows.Forms.DragEventArgs)
If TypeOf sender is TreeView Then
Dim tv As TreeView = CType(sender, TreeView)
Dim pt As Point = tv.PointToClient(New Point(e.X, e.Y))
Dim delta As Integer = tv.Height - pt.Y
If delta < tv.Height / 2 And delta > 0 Then
Dim tn As TreeNode = tv.GetNodeAt(pt.X, pt.Y)
If Not (tn.NextVisibleNode Is Nothing) Then
tn.NextVisibleNode.EnsureVisible()
End If
End If
If delta > tv.Height / 2 And delta < tv.Height Then
Dim tn As TreeNode = tv.GetNodeAt(pt.X, pt.Y)
If Not (tn.PrevVisibleNode Is Nothing) Then
tn.PrevVisibleNode.EnsureVisible()
End If
End If
End If
End Sub 'treeView1_DragOver

24.3 How do I display checkboxes in the nodes of a treeview?

Set the TreeView.CheckBoxes property to true.

24.4 When I right-click a tree node, it does not become selected. How can I make it be selected on a right-
click?

Handle the treeview's mousedown event, and if it is the right-click, then explicitly set focus to th enode
under the click.

private void treeView1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)


{
if(e.Button == MouseButtons.Right)
{
treeView1.SelectedNode = treeView1.GetNodeAt (e.X ,e.Y );
}
}

24.5 When I get the SelectedNode in the treeview's Click event, it is the old selection. How do I get the
newly selected node?
Try using the AfterSelect event instead of the Click event. The Click event is inherited from Control.Click
and occurs before the new selection is set into SelectedNode. The AfterSelect event is fired after the newly
selected node is placed in the SelectedNode property. This code illustrates these events.

private void treeView2_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)


{
TreeNode node = treeView2.SelectedNode;
Console.WriteLine("AfterSelect:" + node.ToString());//from tree
Console.WriteLine("AfterSelect:" + e.Node.ToString());//from event args

private void treeView2_Click(object sender, System.EventArgs e)


{
TreeNode node = treeView2.SelectedNode;
if(node == null)
Console.WriteLine("Click: (none)");
else
Console.WriteLine("Click: " + node.ToString());
}

24.6 How can I get a tooltip to vary from node to node in my treeview?

Try using a MouseMove event handler and checking to see if you have moved to a new node, and if so, set
a new tiptext.

[C#]
private int oldNodeIndex = -1;
private ToolTip toolTip1;

private void Form1_Load(object sender, System.EventArgs e)


{
this.toolTip1 = new System.Windows.Forms.ToolTip();
this.toolTip1.InitialDelay = 300; //half a second delay
this.toolTip1.ReshowDelay = 0;
}

private void treeView1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)


{
TreeNode tn = this.treeView1.GetNodeAt(e.X, e.Y);
if(tn != null)
{
int currentNodeIndex = tn.Index;
if(currentNodeIndex != oldNodeIndex)
{
oldNodeIndex = currentNodeIndex;
if(this.toolTip1 != null && this.toolTip1.Active)
this.toolTip1.Active = false; //turn it off

this.toolTip1.SetToolTip(this.treeView1, string.Format("tooltip: node {0}", oldNodeIndex));


this.toolTip1.Active = true; //make it active so it can show
}
}
}

[VB.NET]
Private oldNodeIndex As Integer = - 1
Private toolTip1 As ToolTip

Private Sub Form1_Load(sender As Object, e As System.EventArgs)


Me.toolTip1 = New System.Windows.Forms.ToolTip()
Me.toolTip1.InitialDelay = 300 'half a second delay
Me.toolTip1.ReshowDelay = 0
End Sub 'Form1_Load

Private Sub treeView1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs)


Dim tn As TreeNode = Me.treeView1.GetNodeAt(e.X, e.Y)
If Not (tn Is Nothing) Then
Dim currentNodeIndex As Integer = tn.Index
If currentNodeIndex <> oldNodeIndex Then
oldNodeIndex = currentNodeIndex
If Not (Me.toolTip1 Is Nothing) And Me.toolTip1.Active Then
Me.toolTip1.Active = False 'turn it off
End If
Me.toolTip1.SetToolTip(Me.treeView1, String.Format("tooltip: node {0}", oldNodeIndex))
Me.toolTip1.Active = True 'make it active so it can show
End If
End If
End Sub 'treeView1_MouseMove

24.7 How can I determine the node level of a node in my treeview?

Here is a code snippet suggested by Mattias Sjögren on the microsoft.public.dotnet.languages.csharp


newsgroup.

[C#]
public int NodeLevel(TreeNode node)
{
int level = 0;
while ((node = node.Parent) != null) level++;
return level;
}
[VB.NET]
Public Sub NodateLevel(ByVal node as TreeNode) As Integer
Dim level as Integer = 0
While Not node Is Nothing
node = node.Parent
level = level + 1
End While
End Sub

24.8 How can I populate a TreeView Control with XML Data?

The following articles on MSDN give you step by step instructions on how you can populate a TreeView
Control with data from an XML file.
C#: Populate a TreeView Control with XML Data in Visual C# .NET
VB.NET: Populate a TreeView Control with XML Data in Visual Basic .NET

24.9 How can I clone/copy all the nodes from one TreeView Control to another?

The following code snippet demonstrates how you can clone or copy all the nodes in TreeView1 to
TreeView2 by clicking on Button1.

[C#]
private void IterateTreeNodes (TreeNode originalNode, TreeNode rootNode)
{
foreach( TreeNode childNode in originalNode.Nodes)
{

TreeNode newNode = new TreeNode(childNode.Text);


newNode.Tag = childNode.Tag;
this.treeView2.SelectedNode = rootNode;
this.treeView2.SelectedNode.Nodes.Add(newNode);
IterateTreeNodes(childNode, newNode);
}
}

//Button Click code


private void button1_Click(object sender, System.EventArgs e)
{
foreach( TreeNode originalNode in this.treeView1.Nodes)
{
TreeNode newNode = new TreeNode(originalNode.Text);
newNode.Tag = originalNode.Tag;
this.treeView2.Nodes.Add(newNode);
IterateTreeNodes(originalNode, newNode);
}
}

[VB.NET]
Private Sub IterateTreeNodes(ByVal originalNode As TreeNode, ByVal rootNode As TreeNode)
Dim childNode As TreeNode
For Each childNode In originalNode.Nodes

Dim NewNode As TreeNode = New TreeNode(childNode.Text)


NewNode.Tag = childNode.Tag
Me.treeView2.SelectedNode = rootNode
Me.treeView2.SelectedNode.Nodes.Add(NewNode)
IterateTreeNodes(childNode, NewNode)
Next
End Sub

'Button Click code


Private Sub button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim originalNode As TreeNode
For Each originalNode In Me.treeView1.Nodes
Dim NewNode As TreeNode = New TreeNode(originalNode.Text)
NewNode.Tag = originalNode.Tag
Me.treeView2.Nodes.Add(NewNode)
IterateTreeNodes(originalNode, NewNode)
Next
End Sub

24.10 How do I programmatically select a node in a TreeView control?

You need to set the HideSelection property of the TreeView to false and call:

[C#]
//Select the first node
this.treeView1.SelectedNode = this.treeView1.Nodes[0];

[VB.NET]

'Select the first node


Me.treeView1.SelectedNode = Me.treeView1.Nodes(0)

24.11 Can I select multiple nodes in a TreeView Control?


The Treeview control does not support multiple selections but there are samples posted at GotDotNet and at
arsdesign.com which demonstrates how this feature can be implemented.

24.12 How can I display a context menu when the user right-clicks on a node in the TreeView control?

You can display a context menu when a user right-clicks on a node by listening to the TreeView's MouseUp
event as shown below:

[C#]
private void treeView1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if(e.Button == MouseButtons.Right)
{
Point ClickPoint = new Point(e.X,e.Y);
TreeNode ClickNode = treeView1.GetNodeAt(ClickPoint);
if(ClickNode == null) return;
// Convert from Tree coordinates to Screen coordinates
Point ScreenPoint = treeView1.PointToScreen(ClickPoint);
// Convert from Screen coordinates to Formc coordinates
Point FormPoint = this.PointToClient(ScreenPoint);
// Show context menu
contextmenu.MenuItems.Clear();
contextmenu.MenuItems.Add("Item1");
contextmenu.MenuItems.Add("Item2");
contextmenu.Show(this,FormPoint);
}
}

[VB.NET]
Private Sub treeView1_MouseUp(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs)
If e.Button = MouseButtons.Right Then
Dim ClickPoint As Point = New Point(e.X,e.Y)
Dim ClickNode As TreeNode = treeView1.GetNodeAt(ClickPoint)
If ClickNode Is Nothing Then
Return
End If
' Convert from Tree coordinates to Screen coordinates
Dim ScreenPoint As Point = treeView1.PointToScreen(ClickPoint)
' Convert from Screen coordinates to Formc coordinates
Dim FormPoint As Point = Me.PointToClient(ScreenPoint)
' Show context menu
contextmenu.MenuItems.Clear()
contextmenu.MenuItems.Add("Item1")
contextmenu.MenuItems.Add("Item2")
contextmenu.Show(this,FormPoint)
End If
End Sub
24.13 How can I ensure that a node is selected when the user clicks along the line of a node?

A click event will be fired but a node will not be selected when the user clicks to the right of a node. This
code snippets show how you can ensure that a node is selected in this scenario:

[C#]
private void treeView1_Click(object sender, System.EventArgs e)
{
treeView1.SelectedNode = treeView1.GetNodeAt(treeView1.PointToClient(Cursor.Position));
}
[VB.NET]
Private Sub treeView1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
treeView1.SelectedNode = treeView1.GetNodeAt(treeView1.PointToClient(Cursor.Position))
End Sub

© 2001-06 Copyright George Shepherd.

25. Windows Forms Button FAQ Home


25.1 How do I autosize a button to fit its text?
25.2 How can I decorate a button face with custom drawing?
25.3 How can I put a bitmap or icon on a button face?
25.4 How can I trigger a button click event?
25.5 How can I get button to fire a click event at specific time intervals while the mouse is down like a
scrollbar button?

25.1 How do I autosize a button to fit its text?

Get a Graphics object for the button and use its MeasureString method to compute the width you need.
Graphics g = button1.CreateGraphics();
float w = g.MeasureString(button1.Text, button1.Font).Width;
g.Dispose();
button1.Width = (int) w + 12; // 12 is for the margins

25.2 How can I decorate a button face with custom drawing?

Subclass Button and add a custom Paint event handler that does you custom drawing.

public class MyButton : System.Windows.Forms.Button


{
public MyButton()
{
this.Paint += new System.Windows.Forms.PaintEventHandler(this.button1_Paint);
}
private void button1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
//custom drawing
Pen pen2 = new Pen(Color.Red);
pen2.Width = 8;
e.Graphics.DrawLine(pen2, 7, 4, 7, this.Height - 4);
pen2.Width = 1;
e.Graphics.DrawEllipse(pen2, this.Width - 16 , 6, 8, 8);
}
}

25.3 How can I put a bitmap or icon on a button face?

You can use the Button.Image property to add an image to a button face. Use the Button.ImageAlign (and
possibly Button.TextAlign) to layout your button face.

You can also implement custom drawing on a button face as described in the FAQ entitled "How can I
decorate a button face with custom drawing".

25.4 How can I trigger a button click event?

Use the button's public method PerformClick.

button1.PerformClick();
25.5 How can I get button to fire a click event at specific time intervals while the mouse is down like a
scrollbar button?

Shawn Burke posted the following solution on the microsoft.public.dotnet.framework.windowsforms


newsgroup.

public class RepeatButton : Button


{
private Timer timer1;

public int Interval


{
get
{
return Timer.Interval;
}
set
{
Timer.Interval = value;
}
}

private Timer Timer


{
get
{
if (timer1 == null)
{
// create and setup our timer.
timer1 = new Timer();
timer1.Tick += new EventHandler(OnTimer);
timer1.Enabled = false;
}
return timer1;
}
}

protected override void OnMouseDown(MouseEventArgs me)


{
base.OnMouseDown(me);

// turn on the timer


Timer.Enabled = true;
}

protected override void OnMouseUp(MouseEventArgs me)


{
// turn off the timer
Timer.Enabled = false;
base.OnMouseUp(me);
}

private void OnTimer(object sender, EventArgs e)


{
// fire off a click on each timer tick
//
OnClick(EventArgs.Empty);
}
}

© 2001-06 Copyright George Shepherd.

26. Windows Forms TabControl FAQ Home


26.1 How do color the tabs on my TabControl?
26.2 How do I programatically select a Tab Page?
26.3 Why do the order of the tabs keep changing when opening and closing the Form?
26.4 How do I force the focus to be on a text box in a tab page when the application gets loaded?
26.5 For a TabControl, how do I make the tabs on the tab pages appear on the bottom instead of on the
right?
26.6 How do I use code to insert or delete tabpages in a TabControl?
26.7 How do I dynamically hide/unhide tabs in a TabControl?
26.8 How do I prevent the user from changing the selected tab page?
26.9 How can I drag and drop TabPages between TabControls?

26.1 How do color the tabs on my TabControl?

Ken Tucker offers this solution. Set the TabControl's DrawMode to OwnerDraw, and then handle the
DrawItem event to draw things yourself. Here are both VB and C# sample projects that display a gradient
tab for the active tabpage.
26.2 How do I programatically select a Tab Page?

There are a couple of ways you could do select a tab page programmatically:

[C#]
//Select the second Tab Page
this.tabControl.SelectedTab = this.tabPage2
or
//Select Second Tab
this.tabControl.SelectedIndex= 1;

[VB.NET]
'Select the second Tab Page
Me.tabControl.SelectedTab = Me.tabPage2
or
'Select Second Tab
Me.tabControl.SelectedIndex= 1

26.3 Why do the order of the tabs keep changing when opening and closing the Form?

This seems to be a known issue with the TabControl designer. The designer seems to automatically reorder
the tabs while serializing changes made in the designer.

To work around this issue, in your constructor, after the call to InitializeComponent, you could remove all
the tab pages and add them back in the desired order.

26.4 How do I force the focus to be on a text box in a tab page when the application gets loaded?

Listen to the Form's Activate event and set focus on the text box (using the Focus method). The common
mistake is to try to set Focus in the Form_Load event. This is not possible because no Controls are visible
at this time and hence focus cannot be set at this time.

26.5 For a TabControl, how do I make the tabs on the tab pages appear on the bottom instead of on the
right?

Set the TabControl.Alignment property to TabAlignment.Bottom.

tabControl1.Alignment = TabAlignment.Bottom;
You can also change the tabs into buttons using the Appearance property and TabAppearance enums.

26.6 How do I use code to insert or delete tabpages in a TabControl?

To delete a tabpage, you use the tabControl1.Controls.Remove method. To add a new page as the last tab,
use the tabControl1.Controls.Add method. Here is some sample code.

//remove the selected tab


tabControl1.Controls.Remove(tabControl1.SelectedTab);

//add a new tabpage as the last tab


tabControl1.Controls.Add(new TabPage("new Page"));

There does not appear to be support in the framework for inserting a tab at a particular position. A work
around might be to save the current tabpage controls, clear the Controls collection, and then add the saved
controls back to the Controls collection inserting a new tab. Here is some code that does this.

private void InsertTab(int tabNumber, ref TabControl tabControl)


{
int limit = tabControl.Controls.Count;
if(tabNumber < 0 || tabNumber > limit)
{
tabControl.Controls.Add(new TabPage("new Page"));
return;
}

int target = tabControl.SelectedIndex;

//save the exisiting pages & clear the controls


Control [] c = new Control[limit];
tabControl.Controls.CopyTo(c, 0);
tabControl.Controls.Clear();

//add the earlier pages


for (int i = 0; i < target; ++i)
tabControl.Controls.Add(c[i]);
//insert the page
tabControl.Controls.Add(new TabPage("new Page"));

//add the later pages


for (int i = target; i < limit; ++i)
tabControl.Controls.Add(c[i]);

//select the new page


tabControl.SelectedIndex = target;
}
26.7 How do I dynamically hide/unhide tabs in a TabControl?

It's a common mistake to try to use the Visible property of the TabPage to make the tab invisible. But this
does not work (The Visible property of the TabPage is essentially obsolete). The TabControl doesn't provide
you an easy way to do so.

The workaround is to remove and add the TabPage from the TabControl whenever you want to hide/unhide
it. Refer to our other faq on how to insert/delete tab pages in a TabControl for more information.

26.8 How do I prevent the user from changing the selected tab page?

You can use the TabPage's Validating event to prevent a new tab page selection. Here are the steps:

1) Every time the user selects a new tab, make sure that the corresponding tab page gets the focus. You can
do so as follows:

// In C#
private void tabControl1_SelectedIndexChanged(object sender,
System.EventArgs e)
{
tabControl1.TabPages[tabControl1.SelectedIndex].Focus();
tabControl1.TabPages[tabControl1.SelectedIndex].CausesValidation = true;
}

'VB.Net
Private Property sender,() As tabControl1_SelectedIndexChanged(object
End Property
Private Function e)() As System.EventArgs
tabControl1.TabPages(tabControl1.SelectedIndex).Focus()
tabControl1.TabPages(tabControl1.SelectedIndex).CausesValidation = True
End Function

Note that CausesValidation should be set to True since you will be listening to the Validating event in the
next step. You will also have to add some code like above when the TabControl is shown the very first time
(like in the Form_Load event handler).

2) Listen to the TabPage's Validating event (which will be called when the user clicks on a different tab
page) and determine whether the user should be allowed to change the selected tab page.

// In C#
private void tabPage1_Validating(object sender,
System.ComponentModel.CancelEventArgs e)
{
if(!checkValidated.Checked)
e.Cancel = true;
}

' In VB.Net
Private Sub tabPage1_Validating(ByVal sender As Object, ByVal e As
System.ComponentModel.CancelEventArgs)
If Not checkValidated.Checked Then
e.Cancel = True
End If
End Sub

26.9 How can I drag and drop TabPages between TabControls?

The following code snippet shows how you can drag a TabPage from TabControl1 and drop it into
TabControl2 (whose AllowDrop property must be set to True): $$ [C#] Source TabControl private void
tabControl1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { if (e.Button ==
MouseButtons.Left) { this.tabControl1.DoDragDrop(this.tabControl1.SelectedTab,DragDropEffects.All); }
} //Target TabControl private void tabControl2_DragEnter(object sender,
System.Windows.Forms.DragEventArgs e) { if(e.Data.GetDataPresent(typeof(TabPage))) { e.Effect =
DragDropEffects.Move; } else e.Effect = DragDropEffects.None; } private void
tabControl2_DragDrop(object sender, System.Windows.Forms.DragEventArgs e) { TabPage DropTab =
(TabPage)(e.Data.GetData (typeof(TabPage))); this.tabControl2.TabPages.Add (DropTab); } [VB.NET]
'Source TabControl Private Sub tabControl1_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) If e.Button = MouseButtons.Left Then
Me.tabControl1.DoDragDrop(Me.tabControl1.SelectedTab,DragDropEffects.All) End If End Sub 'Target
TabControl Private Sub tabControl2_DragEnter(ByVal sender As Object, ByVal e As
System.Windows.Forms.DragEventArgs) If e.Data.GetDataPresent(Type.GetType(TabPage)) Then e.Effect
= DragDropEffects.Move Else e.Effect = DragDropEffects.None End If End Sub Private Sub
tabControl2_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Dim
DropTab As TabPage = CType((e.Data.GetData(Type.GetType(TabPage))), TabPage)
Me.tabControl2.TabPages.Add (DropTab) End Sub $$
© 2001-06 Copyright George Shepherd.

27. Windows Forms TextBox FAQ Home


27.1 How can I prevent the beep when enter is hit in textbox?
27.2 How do I disable pasting into a TextBox (via Ctrl + V and the context menu)?
27.3 How can I disable the right-click context menu in my textbox?
27.4 How do I format numbers, dates and currencies in a TextBox?
27.5 How do I browse for, and read a text file into an TextBox?
27.6 How do I send a EM_XXXX message to a textbox to get some value such as line index in C#?
27.7 How do I prevent a control from receiving focus when it receives a mouseclick?
27.8 How do I make my textbox use all upper (or lower) case characters?
27.9 I have a delete key shortcut for my main menu. When my textbox is being edited, pressing delete
activates this menu items instead of being processed by the TextBox. How can I get my TextBox to handle
this delete?
27.10 How can I use a TextBox to enter a password?
27.11 How can I place a TextBox in overwrite mode instead of insert mode?
27.12 How can I make a ReadOnly TextBox ignore the mousedowns so that you cannot scroll the text or
set the cursor?
27.13 How can I restrict the characters that my textbox can accept?
27.14 How do I set several lines into a multiline textbox?
27.15 When I set a TextBox to Readonly or set Enabled to false, the text color is gray. How can I force it
to be the color specified in the ForeColor property of the TextBox.
27.16 How can I make the focus move to the next control when the user presses the Enter key in a
TextBox?

27.1 How can I prevent the beep when enter is hit in textbox?

You can prevent the beep when the enter key is pressed in a TextBox by deriving the TextBox and
overriding OnKeyPress.

[C#]
public class MyTextBox : TextBox
{
protected override void OnKeyPress(KeyPressEventArgs e)
{
if(e.KeyChar == (char) 13)
e.Handled = true;
else
base.OnKeyPress (e);
}
}
[VB.NET]
Public Class MyTextBox
Inherits TextBox

Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)


If e.KeyChar = CChar(13) Then
e.Handled = True
Else
MyBase.OnKeyPress(e)
End If
End Sub 'OnKeyPress
End Class 'MyTextBox

27.2 How do I disable pasting into a TextBox (via Ctrl + V and the context menu)?

First set the ContextMenu property of the TextBox to a dummy, empty ContextMenu instance. This will
prevent the default context menu from showing. Then, override the ProcessCmdKey method as follows in a
TextBox derived class:

// In C#
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if(keyData == (Keys.Control | Keys.V))
return true;
else
return base.ProcessCmdKey(ref msg, keyData);
}

' In VB.Net
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As
Boolean
If keyData =(Keys.Control | Keys.V) Then
Return True
Else
Return MyBase.ProcessCmdKey( msg, keyData)
End If
End Function

27.3 How can I disable the right-click context menu in my textbox?

You can set the ContextMenu property of the TextBox to a dummy, empty ContextMenu instance.

27.4 How do I format numbers, dates and currencies in a TextBox?


Each type has a ToString method that can be used to accomplished formatting. Also, you can use the
String.Format method to format things as well. To format dates, use the ToString member of DateTime. You
may want to use the InvariantInfo setting (see below) to get culture-independent strings.

27.5 How do I browse for, and read a text file into an TextBox?

You use the Frameworks OpenFileDialog to implement this functionailty.

using System.Text;
using System.IO;
....
private void button1_Click(object sender, System.EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "Open text file" ;
dlg.InitialDirectory = @"c:\" ;
dlg.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" ;

if(dlg.ShowDialog() == DialogResult.OK)
{
StreamReader sr = File.OpenText(dlg.FileName);

string s = sr.ReadLine();
StringBuilder sb = new StringBuilder();
while (s != null)
{
sb.Append(s);
s = sr.ReadLine();
}
sr.Close();
textBox1.Text = sb.ToString();
}
}

27.6 How do I send a EM_XXXX message to a textbox to get some value such as line index in C#?

There is a protected SendMessage call you can use for this purpose, so you have to derive from TextBox.

public MyTextBox : TextBox


{
private const int EM_XXXX = 0x1234;
public int LineIndex
{
get
{
return base.SendMessage(EM_XXXX, 0, 0);
}
}
}

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

27.7 How do I prevent a control from receiving focus when it receives a mouseclick?

You can set the control's Enabled property to false. This will prevent clicking but also gives the disabled
look.

There is a ControlStyles.Selectable flag that determines whether the control can get focus or not. But it
does not appear to affect some controls such as TextBox. But you can prevent the TextBox from getting
focus by overriding its WndProc method and ignoring the mouse down.

public class MyTextBox : TextBox


{
const int WM_LBUTTONDOWN = 0x0201;

protected override void WndProc(ref System.Windows.Forms.Message m)


{
if(m.Msg == WM_LBUTTONDOWN)
return;
base.WndProc(ref m);
}
}

27.8 How do I make my textbox use all upper (or lower) case characters?

Use the CharacterCasing property of the TextBox.

textBox1.CharacterCasing = CharacterCasing.Upper;
// textBox1.CharacterCasing = CharacterCasing.Lower;

27.9 I have a delete key shortcut for my main menu. When my textbox is being edited, pressing delete
activates this menu items instead of being processed by the TextBox. How can I get my TextBox to handle
this delete?
Subclass the TextBox and override its PreProcessMessage method.

public class MyTextBox : TextBox


{

const int WM_KEYDOWN = 0x100;


const int WM_KEYUP = 0x101;

public override bool PreProcessMessage( ref Message msg )


{
Keys keyCode = (Keys)(int)msg.WParam & Keys.KeyCode;
if((msg.Msg == WM_KEYDOWN || msg.Msg == WM_KEYUP)
&& keyCode == Keys.Delete)
{
return false;
}
return base.PreProcessMessage(ref msg);
}
}

27.10 How can I use a TextBox to enter a password?

Set the TextBox.PasswordChar property for the textbox.

textBox1.PasswordChar = '\u25CF';

27.11 How can I place a TextBox in overwrite mode instead of insert mode?

You can handle the textbox's KeyPress event and if you want the keypress to be an overwrite, just select the
current character so the keypress will replace it. The attached sample has a derived textbox that has an
OverWrite property and a right-click menu that allows you to toggle this property.

The snippet below shows you a KeyPress handler that automatically does an overwrite if the maxlength of
the textbox has been hit. This does not require a derived class.

private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)


{
if(textBox1.Text.Length == textBox1.MaxLength && textBox1.SelectedText == "")
{
textBox1.SelectionLength = 1;
}
}
27.12 How can I make a ReadOnly TextBox ignore the mousedowns so that you cannot scroll the text or
set the cursor?

You can do this by deriving the TextBox, overriding the WndProc method and ignoring these mousedowns.

[C#]
public class MyTextBox : TextBox
{
protected override void WndProc(ref System.Windows.Forms.Message m)
{ // WM_NCLBUTTONDOWN WM_LBUTTONDOWN
if(this.ReadOnly && (m.Msg == 0xa1 || m.Msg == 0x201))
{
return; //ignore it
}
base.WndProc(ref m);
}
}
[VB.NET]
Public Class MyTextBox
Inherits TextBox

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)


' WM_NCLBUTTONDOWN WM_LBUTTONDOWN
If Me.ReadOnly AndAlso(m.Msg = &HA1 OrElse m.Msg = &H201) Then
Return 'ignore it
End If
MyBase.WndProc(m)
End Sub 'WndProc
End Class 'MyTextBox

27.13 How can I restrict the characters that my textbox can accept?

You can handle the textbox's KeyPress event and if the char passed in is not acceptable, mark the events
argument as showing the character has been handled. Below is a derived TextBox that only accepts digits
(and control characters such as backspace, ...). Even though the snippet uses a derived textbox, it is not
necessary as you can just add the handler to its parent form.

[C#]
public class NumbersOnlyTextBox : TextBox
{
public NumbersOnlyTextBox()
{
this.KeyPress += new KeyPressEventHandler(HandleKeyPress);
}
private void HandleKeyPress(object sender, KeyPressEventArgs e)
{
if(!char.IsDigit(e.KeyChar) && !char.IsControl(e.KeyChar))
e.Handled = true;
}
}

[VB.NET]
Public Class NumbersOnlyTextBox
Inherits TextBox

Public Sub New()


AddHandler Me.KeyPress, AddressOf HandleKeyPress
End Sub 'New

Private Sub HandleKeyPress(sender As Object, e As KeyPressEventArgs)


If Not Char.IsDigit(e.KeyChar) And Not Char.IsControl(e.KeyChar) Then
e.Handled = True
End If
End Sub 'HandleKeyPress
End Class 'NumbersOnlyTextBox

27.14 How do I set several lines into a multiline textbox?

There are a several of ways to do this. Here are a few:

1) Insert a carraige return-linefeed, "\r\n", between your lines.

textBox1.Text = "This is line 1.\r\nThis is line 2";


// or textBox1.Text = stringvar1 + "\r\n" + stringvar2;

2) Use the Environment.NewLine property. This property is normally set to "\r\n".

textBox1.Text = "This is line 1." + Environment.NewLine + "This is line 2";

3) Use the Lines property of the TextBox. Make sure you populate your array before you set the property.

string[] arr = new string[2];


arr[0] = "this is line1";
arr[1] = "this is line 2";

textBox3.Lines = arr;
27.15 When I set a TextBox to Readonly or set Enabled to false, the text color is gray. How can I force it to
be the color specified in the ForeColor property of the TextBox.

Felix Wu gives this solution in the microsoft.public.dotnet.frameworks.windowsforms newgroup.

You can download a VB.NET sample.

Override the OnPaint event of the TextBox. For example:

protected override void OnPaint(PaintEventArgs e)


{
SolidBrush drawBrush = new SolidBrush(ForeColor); //Use the ForeColor property
// Draw string to screen.
e.Graphics.DrawString(Text, Font, drawBrush, 0f,0f); //Use the Font property
}

Note: You need to set the ControlStyles to "UserPaint" in the constructor.

public MyTextBox()
{
// This call is required by the Windows.Forms Form Designer.
this.SetStyle(ControlStyles.UserPaint,true);

InitializeComponent();

// TODO: Add any initialization after the InitForm call


}

27.16 How can I make the focus move to the next control when the user presses the Enter key in a
TextBox?

Add a handler for your TextBox's KeyDown event. (This assumes you set the AcceptsReturn property to
False). Then in your KeyDown eventhandler, have code such as:

[C#]
if (e.KeyCode = Keys.Enter)
SendKeys.Send("{TAB}");

[VB.NET]
If e.KeyCode = Keys.Enter Then
SendKeys.Send("{TAB}")
EndIf
© 2001-06 Copyright George Shepherd.

28. Windows Forms Cursors FAQ Home


28.1 I set the wait cursor using Cursor.Current = Cursors.WaitCursor;. Why does does it disappear
before I want it to?
28.2 How do I change the cursor for a control?
28.3 How to convert a Cursor class to a .cur file?
28.4 How to load and display a cursor from a resource manifest?

28.1 I set the wait cursor using Cursor.Current = Cursors.WaitCursor;. Why does does it disappear before I
want it to?

Setting the Current property changes the cursor and stops the processing of mouse events. Setting the
cursor back to Cursors.Default restarts the mouse event processing and displays the proper cursor for each
control. If a DoEvents is called before you reset the cursor back to the default, this will also start up the
mouse event processing and you will lose the particular cursor you set. So, if your WaitCursor is
disappearring, one explanation might be that DoEvents is getting called.

Here is some code that sets a WaitCursor.

Cursor oldCursor = Cursor.Current;


Cursor.Current = Cursors.WaitCursor;
try
{
// Do your processing that takes time...
// eg. let's wait for 2 seconds...
DateTime dt = DateTime.Now.AddSeconds(2);
while(dt > DateTime.Now)
{ //do nothing
}
}
finally
{
Cursor.Current = oldCursor;
}
28.2 How do I change the cursor for a control?

Try

button1.Cursor = new System.Windows.Forms.Cursor(@"C:\winnt\cursors\hnodrop.cur");

28.3 How to convert a Cursor class to a .cur file?

protected void WriteCursorToFile(Cursor cursor, string fileName)


{
byte[] blob =
TypeDescriptor.GetConverter(typeof(System.Windows.Forms.Cursor)).ConvertTo(cursor, typeof(byte[]))
as byte[];

if(blob != null)
{
FileStream fileStream = new FileStream(fileName, FileMode.Create);
fileStream.Write(blob, 0, blob.Length);
fileStream.Flush();
fileStream.Close();
}
else
MessageBox.Show("Unable to convert Cursor to byte[]");
}

28.4 How to load and display a cursor from a resource manifest?

System.IO.Stream strm = null;


try
{
string curName = "WindowsApplication1.Cursor1.cur";
strm = this.GetType().Assembly.GetManifestResourceStream(curName);
this.Cursor = new Cursor(strm);
}
catch(Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
finally
{
if(strm != null)
strm.Close();
}
© 2001-06 Copyright George Shepherd.

29. Windows Forms WebBrowser FAQ Home


29.1 How can I host a WebBrowser control in a Windows Form?
29.2 How can I enable editing for the WebBrowser?
29.3 How can I catch the BeforeNavigate2 event?
29.4 WebBrowser control does not seem to be cleaning up temp files. How can this be done?
29.5 How can I use MSHTML to edit HTML in a Windows Forms control?

29.1 How can I host a WebBrowser control in a Windows Form?

We have two suggestions with sample projects how you host a WebBrowser control inside a form and
display HTML contents and listen to events such as NavigateComplete or BeforeNavigate. Of course there
are many other ways to do this.

Download htmlviewer.zip for two sample projects for the suggestions discussed below.

1) The first suggestion is to generate an ActiveX wrapper for shdocvw using the aximp tool.
The command line for this tool should be as follows:

aximp c:\windows\system32\shdocvw.dll

This will generate the following assemblies.

Generated Assembly: D:\Syncfusion\faq\HtmlBrowser\HtmlViewer2\SHDocVw.dll


Generated Assembly: D:\Syncfusion\faq\HtmlBrowser\HtmlViewer2\AxSHDocVw.dll

Now you can reference these dlls in your project and use AxWebBrowser. In the attached HtmlViewer2
sample we have derived a HtmlControl class from AxWebBrowser and added some properties that let you
specify a CSS Stylesheet and the Html content as a string.
2) Our second sample lets you bypass the generation of a ActiveX wrapper. You don't have to include and
ship shdocvw.dll and axshdocvw.dll. In the attached HtmlViewer sample, we derived from AxHost and
attached our own IWebBrowserEvents interface by overriding the CreateSink, AttachInterfaces and
DetachSink methods.

You can use HtmlControl in your form and specify HTML content by assigning a HTML string to
HtmlControl. A cascading style sheet can be specified by assigning a path name to the CascadingStyleSheet
property. The sample demonstrates how to use a CSS style sheet that has been embedded as a resource in
the assembly.

29.2 How can I enable editing for the WebBrowser?

You can set the content editable by getting a reference to a IHTMLElement3 element and initializing the
contentEditable property with "true".

private void EnableEditing()


{
IHTMLDocument3 doc = (IHTMLDocument3) browser.GetDocument();
if (doc != null)
{
IHTMLElement3 el = (IHTMLElement3) doc.GetBody();
el.contentEditable = "true";
}
}

If you want to read out contents of a specific element use an id in the html source:

<span id="EditText">EditableText</span>

From CSharp you can reference this text with

IHTMLElement3 el = (IHTMLElement3) doc.getElementById("EditText");


MessageBox.Show(el.GetInnerText());
MessageBox.Show(el.GetInnerHTML());

You can use IHTMLDocument3 and IHTMLElement3 interface definitions from the imported type library
dll C:\Program Files\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll

[
Guid(@"3050F485-98B5-11CF-BB82-00AA00BDCE0B"),
TypeLibType(TypeLibTypeFlags.FDispatchable|TypeLibTypeFlags.FDual)
]
public interface IHTMLDocument3 : IHTMLDocument2
{
[DispId(1072 /*0x0430*/)]
void releaseCapture();

[DispId(1073 /*0x0431*/)]
void recalc(bool fForce);

[DispId(1074 /*0x0432*/)]
[return: MarshalAs(UnmanagedType.Interface)]
object createTextNode(string text);

[DispId(1075 /*0x0433*/)]
IHTMLElement documentElement
{
[return: MarshalAs(UnmanagedType.Interface)] get; }

[DispId(1077 /*0x0435*/)]
string uniqueID
{
[return: MarshalAs(UnmanagedType.BStr)] get; }

[DispId(-2147417605 /*0x800101FB*/)]
bool attachEvent(string _event, object pdisp);

[DispId(-2147417604 /*0x800101FC*/)]
void detachEvent(string _event, object pdisp);

[DispId(-2147412050 /*0x800117AE*/)]
object onrowsdelete
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412049 /*0x800117AF*/)]
object onrowsinserted
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412048 /*0x800117B0*/)]
object oncellchange
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412072 /*0x80011798*/)]
object ondatasetchanged
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }
[DispId(-2147412071 /*0x80011799*/)]
object ondataavailable
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412070 /*0x8001179A*/)]
object ondatasetcomplete
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412065 /*0x8001179F*/)]
object onpropertychange
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412995 /*0x800113FD*/)]
string dir
{
set; [return: MarshalAs(UnmanagedType.BStr)] get; }

[DispId(-2147412047 /*0x800117B1*/)]
object oncontextmenu
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412044 /*0x800117B4*/)]
object onstop
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(1076 /*0x0434*/)]
[return: MarshalAs(UnmanagedType.Interface)]
IHTMLDocument2 createDocumentFragment();

[DispId(1078 /*0x0436*/)]
IHTMLDocument2 parentDocument
{
[return: MarshalAs(UnmanagedType.Interface)] get; }

[DispId(1079 /*0x0437*/)]
bool enableDownload
{
set; get; }

[DispId(1080 /*0x0438*/)]
string baseUrl
{
set; [return: MarshalAs(UnmanagedType.BStr)] get; }

[DispId(-2147417063 /*0x80010419*/)]
object childNodes
{
[return: MarshalAs(UnmanagedType.IDispatch)] get; }

[DispId(1082 /*0x043A*/)]
bool inheritStyleSheets
{
set; get; }

[DispId(-2147412043 /*0x800117B5*/)]
object onbeforeeditfocus
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(1086 /*0x043E*/)]
[return: MarshalAs(UnmanagedType.Interface)]
object getElementsByName(string v);

[DispId(1088 /*0x0440*/)]
[return: MarshalAs(UnmanagedType.Interface)]
IHTMLElement getElementById(string v);

[DispId(1087 /*0x043F*/)]
[return: MarshalAs(UnmanagedType.Interface)]
object getElementsByTagName(string v);
}

[
InterfaceType(ComInterfaceType.InterfaceIsDual),
ComVisible(true),
Guid(@"332C4425-26CB-11D0-B483-00C04FD90119")
]
public interface IHTMLDocument2
{
[return: MarshalAs(UnmanagedType.Interface)]
object GetScript();

[return: MarshalAs(UnmanagedType.Interface)]
object GetAll();

[return: MarshalAs(UnmanagedType.Interface)]
IHTMLElement GetBody();

[return: MarshalAs(UnmanagedType.Interface)]
object GetActiveElement();

[return: MarshalAs(UnmanagedType.Interface)]
object GetImages();

[return: MarshalAs(UnmanagedType.Interface)]
object GetApplets();
[return: MarshalAs(UnmanagedType.Interface)]
object GetLinks();

[return: MarshalAs(UnmanagedType.Interface)]
object GetForms();

[return: MarshalAs(UnmanagedType.Interface)]
object GetAnchors();

void SetTitle(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetTitle();

[return: MarshalAs(UnmanagedType.Interface)]
object GetScripts();

void SetDesignMode(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetDesignMode();

[return: MarshalAs(UnmanagedType.Interface)]
object GetSelection();

[return: MarshalAs(UnmanagedType.BStr)]
string GetReadyState();

[return: MarshalAs(UnmanagedType.Interface)]
object GetFrames();

[return: MarshalAs(UnmanagedType.Interface)]
object GetEmbeds();

[return: MarshalAs(UnmanagedType.Interface)]
object GetPlugins();

void SetAlinkColor(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetAlinkColor();

void SetBgColor(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetBgColor();

void SetFgColor(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetFgColor();
void SetLinkColor(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetLinkColor();

void SetVlinkColor(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetVlinkColor();

[return: MarshalAs(UnmanagedType.BStr)]
string GetReferrer();

[return: MarshalAs(UnmanagedType.Interface)]
object GetLocation();

[return: MarshalAs(UnmanagedType.BStr)]
string GetLastModified();

void SetURL(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetURL();

void SetDomain(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetDomain();

void SetCookie(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetCookie();

void SetExpando(bool p);

[return: MarshalAs(UnmanagedType.Bool)]
bool GetExpando();

void SetCharset(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetCharset();

void SetDefaultCharset(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetDefaultCharset();

[return: MarshalAs(UnmanagedType.BStr)]
string GetMimeType();

[return: MarshalAs(UnmanagedType.BStr)]
string GetFileSize();

[return: MarshalAs(UnmanagedType.BStr)]
string GetFileCreatedDate();

[return: MarshalAs(UnmanagedType.BStr)]
string GetFileModifiedDate();

[return: MarshalAs(UnmanagedType.BStr)]
string GetFileUpdatedDate();

[return: MarshalAs(UnmanagedType.BStr)]
string GetSecurity();

[return: MarshalAs(UnmanagedType.BStr)]
string GetProtocol();

[return: MarshalAs(UnmanagedType.BStr)]
string GetNameProp();

void DummyWrite(int psarray);

void DummyWriteln(int psarray);

[return: MarshalAs(UnmanagedType.Interface)]
object Open(string URL, object name, object features, object replace);

void Close();

void Clear();

[return: MarshalAs(UnmanagedType.Bool)]
bool QueryCommandSupported(string cmdID);

[return: MarshalAs(UnmanagedType.Bool)]
bool QueryCommandEnabled(string cmdID);

[return: MarshalAs(UnmanagedType.Bool)]
bool QueryCommandState(string cmdID);

[return: MarshalAs(UnmanagedType.Bool)]
bool QueryCommandIndeterm(string cmdID);

[return: MarshalAs(UnmanagedType.BStr)]
string QueryCommandText(string cmdID);

[return: MarshalAs(UnmanagedType.Struct)]
object QueryCommandValue(string cmdID);
[return: MarshalAs(UnmanagedType.Bool)]
bool ExecCommand(string cmdID, bool showUI, object value);

[return: MarshalAs(UnmanagedType.Bool)]
bool ExecCommandShowHelp(string cmdID);

[return: MarshalAs(UnmanagedType.Interface)]
object CreateElement(string eTag);

void SetOnhelp(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnhelp();

void SetOnclick(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnclick();

void SetOndblclick(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOndblclick();

void SetOnkeyup(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnkeyup();

void SetOnkeydown(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnkeydown();

void SetOnkeypress(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnkeypress();

void SetOnmouseup(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmouseup();

void SetOnmousedown(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmousedown();

void SetOnmousemove(object p);


[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmousemove();

void SetOnmouseout(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmouseout();

void SetOnmouseover(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmouseover();

void SetOnreadystatechange(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnreadystatechange();

void SetOnafterupdate(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnafterupdate();

void SetOnrowexit(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnrowexit();

void SetOnrowenter(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnrowenter();

void SetOndragstart(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOndragstart();

void SetOnselectstart(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnselectstart();

[return: MarshalAs(UnmanagedType.Interface)]
object ElementFromPoint(int x, int y);

[return: MarshalAs(UnmanagedType.Interface)]
object GetParentWindow();

[return: MarshalAs(UnmanagedType.Interface)]
object GetStyleSheets();

void SetOnbeforeupdate(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnbeforeupdate();

void SetOnerrorupdate(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnerrorupdate();

[return: MarshalAs(UnmanagedType.BStr)]
string toString();

[return: MarshalAs(UnmanagedType.Interface)]
object CreateStyleSheet(string bstrHref, int lIndex);
}

[
Guid(@"3050F434-98B5-11CF-BB82-00AA00BDCE0B"),
TypeLibType(TypeLibTypeFlags.FDispatchable|TypeLibTypeFlags.FDual)
]
public interface IHTMLElement2 : IHTMLElement
{

// Methods

[DispId(-2147417073 /*0x8001040F*/)]
string scopeName
{
[return: MarshalAs(UnmanagedType.BStr)] get; }

[DispId(-2147417072 /*0x80010410*/)]
void setCapture(bool containerCapture);

[DispId(-2147417071 /*0x80010411*/)]
void releaseCapture();

[DispId(-2147412066 /*0x8001179E*/)]
object onlosecapture
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147417070 /*0x80010412*/)]
[return: MarshalAs(UnmanagedType.BStr)]
string componentFromPoint(int x, int y);

[DispId(-2147417069 /*0x80010413*/)]
void doScroll(object component);
[DispId(-2147412081 /*0x8001178F*/)]
object onscroll
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412063 /*0x800117A1*/)]
object ondrag
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412062 /*0x800117A2*/)]
object ondragend
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412061 /*0x800117A3*/)]
object ondragenter
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412060 /*0x800117A4*/)]
object ondragover
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412059 /*0x800117A5*/)]
object ondragleave
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412058 /*0x800117A6*/)]
object ondrop
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412054 /*0x800117AA*/)]
object onbeforecut
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412057 /*0x800117A7*/)]
object oncut
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412053 /*0x800117AB*/)]
object onbeforecopy
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412056 /*0x800117A8*/)]
object oncopy
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412052 /*0x800117AC*/)]
object onbeforepaste
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412055 /*0x800117A9*/)]
object onpaste
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147417105 /*0x800103EF*/)]
object currentStyle
{
[return: MarshalAs(UnmanagedType.Interface)] get; }

[DispId(-2147412065 /*0x8001179F*/)]
object onpropertychange
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147417068 /*0x80010414*/)]
[return: MarshalAs(UnmanagedType.Interface)]
object getClientRects();

[DispId(-2147417067 /*0x80010415*/)]
[return: MarshalAs(UnmanagedType.Interface)]
object getBoundingClientRect();

[DispId(-2147417608 /*0x800101F8*/)]
void setExpression(string propname, string expression, string language);

[DispId(-2147417607 /*0x800101F9*/)]
[return: MarshalAs(UnmanagedType.Struct)]
object getExpression(string propname);

[DispId(-2147417606 /*0x800101FA*/)]
bool removeExpression(string propname);

[DispId(-2147418097 /*0x8001000F*/)]
short tabIndex
{
set; get; }

[DispId(-2147416112 /*0x800107D0*/)]
void focus();

[DispId(-2147416107 /*0x800107D5*/)]
string accessKey
{
set; [return: MarshalAs(UnmanagedType.BStr)] get; }

[DispId(-2147412097 /*0x8001177F*/)]
object onblur
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412098 /*0x8001177E*/)]
object onfocus
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412076 /*0x80011794*/)]
object onresize
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147416110 /*0x800107D2*/)]
void blur();

[DispId(-2147416095 /*0x800107E1*/)]
void addFilter(object pUnk);

[DispId(-2147416094 /*0x800107E2*/)]
void removeFilter(object pUnk);

[DispId(-2147416093 /*0x800107E3*/)]
int clientHeight
{
get; }

[DispId(-2147416092 /*0x800107E4*/)]
int clientWidth
{
get; }

[DispId(-2147416091 /*0x800107E5*/)]
int clientTop
{
get; }

[DispId(-2147416090 /*0x800107E6*/)]
int clientLeft
{
get; }

[DispId(-2147417605 /*0x800101FB*/)]
bool attachEvent(string _event, object pdisp);
[DispId(-2147417604 /*0x800101FC*/)]
void detachEvent(string _event, object pdisp);

[DispId(-2147412996 /*0x800113FC*/)]
object readyState
{
[return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412087 /*0x80011789*/)]
object onreadystatechange
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412050 /*0x800117AE*/)]
object onrowsdelete
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412049 /*0x800117AF*/)]
object onrowsinserted
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412048 /*0x800117B0*/)]
object oncellchange
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412995 /*0x800113FD*/)]
string dir
{
set; [return: MarshalAs(UnmanagedType.BStr)] get; }

[DispId(-2147417056 /*0x80010420*/)]
[return: MarshalAs(UnmanagedType.IDispatch)]
object createControlRange();

[DispId(-2147417055 /*0x80010421*/)]
int scrollHeight
{
get; }

[DispId(-2147417054 /*0x80010422*/)]
int scrollWidth
{
get; }

[DispId(-2147417053 /*0x80010423*/)]
int scrollTop
{
set; get; }
[DispId(-2147417052 /*0x80010424*/)]
int scrollLeft
{
set; get; }

[DispId(-2147417050 /*0x80010426*/)]
void clearAttributes();

[DispId(-2147417049 /*0x80010427*/)]
void mergeAttributes(IHTMLElement mergeThis);

[DispId(-2147412047 /*0x800117B1*/)]
object oncontextmenu
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147417043 /*0x8001042D*/)]
[return: MarshalAs(UnmanagedType.Interface)]
IHTMLElement insertAdjacentElement(string where, IHTMLElement insertedElement);

[DispId(-2147417047 /*0x80010429*/)]
[return: MarshalAs(UnmanagedType.Interface)]
IHTMLElement applyElement(IHTMLElement apply, string where);

[DispId(-2147417042 /*0x8001042E*/)]
[return: MarshalAs(UnmanagedType.BStr)]
string getAdjacentText(string where);

[DispId(-2147417041 /*0x8001042F*/)]
[return: MarshalAs(UnmanagedType.BStr)]
string replaceAdjacentText(string where, string newText);

[DispId(-2147417040 /*0x80010430*/)]
bool canHaveChildren
{
get; }

[DispId(-2147417032 /*0x80010438*/)]
int addBehavior(string bstrUrl, ref object pvarFactory);

[DispId(-2147417031 /*0x80010439*/)]
bool removeBehavior(int cookie);

[DispId(-2147417048 /*0x80010428*/)]
object runtimeStyle
{
[return: MarshalAs(UnmanagedType.Interface)] get; }

[DispId(-2147417030 /*0x8001043A*/)]
object behaviorUrns
{
[return: MarshalAs(UnmanagedType.IDispatch)] get; }

[DispId(-2147417029 /*0x8001043B*/)]
string tagUrn
{
set; [return: MarshalAs(UnmanagedType.BStr)] get; }

[DispId(-2147412043 /*0x800117B5*/)]
object onbeforeeditfocus
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147417028 /*0x8001043C*/)]
int readyStateValue
{
get; }

[DispId(-2147417027 /*0x8001043D*/)]
[return: MarshalAs(UnmanagedType.Interface)]
object getElementsByTagName(string v);
} // end of class mshtml.IHTMLElement2

[
TypeLibType(TypeLibTypeFlags.FDispatchable|TypeLibTypeFlags.FDual),
Guid(@"3050F673-98B5-11CF-BB82-00AA00BDCE0B")
]
public interface IHTMLElement3 : IHTMLElement2
{

// Methods

[DispId(-2147417016 /*0x80010448*/)]
void mergeAttributes(IHTMLElement mergeThis, ref object pvarFlags);

[DispId(-2147417015 /*0x80010449*/)]
bool isMultiLine
{
get; }

[DispId(-2147417014 /*0x8001044A*/)]
bool canHaveHTML
{
get; }

[DispId(-2147412039 /*0x800117B9*/)]
object onlayoutcomplete
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412038 /*0x800117BA*/)]
object onpage
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147417012 /*0x8001044C*/)]
bool inflateBlock
{
set; get; }

[DispId(-2147412035 /*0x800117BD*/)]
object onbeforedeactivate
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147417011 /*0x8001044D*/)]
void setActive();

[DispId(-2147412950 /*0x8001142A*/)]
string contentEditable
{
set; [return: MarshalAs(UnmanagedType.BStr)] get; }

[DispId(-2147417010 /*0x8001044E*/)]
bool isContentEditable
{
get; }

[DispId(-2147412949 /*0x8001142B*/)]
bool hideFocus
{
set; get; }

[DispId(-2147418036 /*0x8001004C*/)]
bool disabled
{
set; get; }

[DispId(-2147417007 /*0x80010451*/)]
bool isDisabled
{
get; }

[DispId(-2147412034 /*0x800117BE*/)]
object onmove
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412033 /*0x800117BF*/)]
object oncontrolselect
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }
[DispId(-2147417006 /*0x80010452*/)]
bool FireEvent(string bstrEventName, ref object pvarEventObject);

[DispId(-2147412029 /*0x800117C3*/)]
object onresizestart
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412028 /*0x800117C4*/)]
object onresizeend
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412031 /*0x800117C1*/)]
object onmovestart
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412030 /*0x800117C2*/)]
object onmoveend
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412027 /*0x800117C5*/)]
object onmouseenter
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412026 /*0x800117C6*/)]
object onmouseleave
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412025 /*0x800117C7*/)]
object onactivate
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147412024 /*0x800117C8*/)]
object ondeactivate
{
set; [return: MarshalAs(UnmanagedType.Struct)] get; }

[DispId(-2147417005 /*0x80010453*/)]
bool dragDrop();

[DispId(-2147417004 /*0x80010454*/)]
int glyphMode
{
get; }
} // end of class mshtml.IHTMLElement3

[
ComVisible(true),
Guid(@"3050F1FF-98B5-11CF-BB82-00AA00BDCE0B"),
InterfaceType(ComInterfaceType.InterfaceIsDual)
]
public interface IHTMLElement
{
void SetAttribute(string strAttributeName, object AttributeValue, int lFlags);

void GetAttribute(string strAttributeName, int lFlags, object[] pvars);

[return: MarshalAs(UnmanagedType.Bool)]
bool RemoveAttribute(string strAttributeName, int lFlags);

void SetClassName(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetClassName();

void SetId(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetId();

[return: MarshalAs(UnmanagedType.BStr)]
string GetTagName();

[return: MarshalAs(UnmanagedType.Interface)]
IHTMLElement GetParentElement();

[return: MarshalAs(UnmanagedType.Interface)]
object GetStyle();

void SetOnhelp(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnhelp();

void SetOnclick(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnclick();

void SetOndblclick(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOndblclick();

void SetOnkeydown(object p);


[return: MarshalAs(UnmanagedType.Struct)]
object GetOnkeydown();

void SetOnkeyup(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnkeyup();

void SetOnkeypress(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnkeypress();

void SetOnmouseout(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmouseout();

void SetOnmouseover(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmouseover();

void SetOnmousemove(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmousemove();

void SetOnmousedown(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmousedown();

void SetOnmouseup(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnmouseup();

[return: MarshalAs(UnmanagedType.Interface)]
object GetDocument();

void SetTitle(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetTitle();

void SetLanguage(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetLanguage();
void SetOnselectstart(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnselectstart();

void ScrollIntoView(object varargStart);

[return: MarshalAs(UnmanagedType.Bool)]
bool Contains(IHTMLElement pChild);

[return: MarshalAs(UnmanagedType.I4)]
int GetSourceIndex();

[return: MarshalAs(UnmanagedType.Struct)]
object GetRecordNumber();

void SetLang(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetLang();

[return: MarshalAs(UnmanagedType.I4)]
int GetOffsetLeft();

[return: MarshalAs(UnmanagedType.I4)]
int GetOffsetTop();

[return: MarshalAs(UnmanagedType.I4)]
int GetOffsetWidth();

[return: MarshalAs(UnmanagedType.I4)]
int GetOffsetHeight();

[return: MarshalAs(UnmanagedType.Interface)]
IHTMLElement GetOffsetParent();

void SetInnerHTML(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetInnerHTML();

void SetInnerText(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetInnerText();

void SetOuterHTML(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetOuterHTML();
void SetOuterText(string p);

[return: MarshalAs(UnmanagedType.BStr)]
string GetOuterText();

void InsertAdjacentHTML(string where, string html);

void InsertAdjacentText(string where, string text);

[return: MarshalAs(UnmanagedType.Interface)]
IHTMLElement GetParentTextEdit();

[return: MarshalAs(UnmanagedType.Bool)]
bool GetIsTextEdit();

void Click();

[return: MarshalAs(UnmanagedType.Interface)]
object GetFilters();

void SetOndragstart(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOndragstart();

[return: MarshalAs(UnmanagedType.BStr)]
string toString();

void SetOnbeforeupdate(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnbeforeupdate();

void SetOnafterupdate(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnafterupdate();

void SetOnerrorupdate(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnerrorupdate();

void SetOnrowexit(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnrowexit();

void SetOnrowenter(object p);


[return: MarshalAs(UnmanagedType.Struct)]
object GetOnrowenter();

void SetOndatasetchanged(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOndatasetchanged();

void SetOndataavailable(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOndataavailable();

void SetOndatasetcomplete(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOndatasetcomplete();

void SetOnfilterchange(object p);

[return: MarshalAs(UnmanagedType.Struct)]
object GetOnfilterchange();

[return: MarshalAs(UnmanagedType.Interface)]
object GetChildren();

[return: MarshalAs(UnmanagedType.Interface)]
object GetAll();
}

29.3 How can I catch the BeforeNavigate2 event?

This is a known bug. See http://support.microsoft.com/default.aspx?scid=KB;EN-


US;Q311298&ID=KB;EN-US;

If you are using the second solution from our FAQ "How can I host a WebBrowser control in a Windows
Form" you will not have this problem but if you use the automatically generated wrapper classes see the
following solution:

John Cullen posted the following answer in the microsoft.public.dotnet.framework.interop newsgroup.

The problem of the BeforeNavigate2 event not firing in C# applications has been floating around various
groups for several months. Microsoft have not yet fixed the problem, although it is documented in the
knowledge base. Until they do provide a fix, I suggest the following workaround to the problem which uses
the fact the the old Webbrowser_V1 BeforeNavigate event *can* be caught. Note, use of this interface is
deprecated, however since there doesn't appear to be any chance of a fix any time soon...
...

// define the webbrowser object


private AxSHDocVw.AxWebBrowser axDocument;

// define an IE3 compatible webbrowser object.


private SHDocVw.WebBrowser_V1 axDocumentV1;

public Form1()
{
//...
object o = null;
axDocument.Navigate("about:blank", ref o, ref o, ref o, ref o);
object oOcx = axDocument.GetOcx();
try
{
axDocumentV1 = oOcx as WebBrowser_V1;
axDocumentV1.BeforeNavigate += new
SHDocVw.DWebBrowserEvents_BeforeNavigateEventHandler(this.axDocumentV1_BeforeNavigate);
}
catch (Exception ex)
{
// ignore errors. If it doesn't work, there's not a lot to do!
Console.WriteLine("Add BeforeNavigate event handler failed with{0}.", ex.Message);
}
//...
}

private void axDocumentV1_BeforeNavigate(string URL, int Flags, string TargetFrameName, ref object
PostData, string Headers, ref bool Processed)
{
Console.WriteLine("BeforeNavigateURL= {0}", URL);
//false= allow navigate to continue.
//true= cancel navigation.
Processed=false;
}

29.4 WebBrowser control does not seem to be cleaning up temp files. How can this be done?

Look at the following articles to clear up Cache:

Visual Basic .NET version:

Q311289 - HOW TO: Clear the Cache When Your Application Hosts WebBrowser
http://support.microsoft.com/support/kb/articles/q311/2/89.asp.
C# Version:

Q326201 - HOW TO: Clear the Cache When Your Application Hosts WebBrowser
http://support.microsoft.com/support/kb/articles/q326/2/01.asp.

Posted by Bharat Patel (MS) on microsoft.public.dotnet.framework.windowsforms.

29.5 How can I use MSHTML to edit HTML in a Windows Forms control?

Take a look at Tim Anderson's HTMLEditor control which is a wrapper for MSHTML.

© 2001-06 Copyright George Shepherd.

30. Windows Forms ProgressBars FAQ Home


30.1 How can I implement a smooth ProgressBar?

30.1 How can I implement a smooth ProgressBar?

Refer to the following KnowledgeBase articles in MSDN:


HOW TO: Create a Smooth Progress Bar in Visual C# .NET
HOW TO: Create a Smooth ProgressBar in Visual Basic .NET

© 2001-06 Copyright George Shepherd.


31. Windows Forms PictureBox FAQ Home
31.1 How can I place a border around a PictureBox?
31.2 How can I copy a bitmap from the clipboard to a PictureBox?
31.3 How can I copy and paste images/graphs etc from MS Office to a PictureBox?
31.4 How can I drag and drop an image from one PictureBox to another?

31.1 How can I place a border around a PictureBox?

One solution is to use a panel that has a picturebox placed on it with DockStyle.Fill. This will make the
picturebox assume the size of the panel. In addition, set the DockPadding.All property to the width of the
desired border. Then in the Panel's OnPaint method, call the baseclass and then paint the desired borders.

Here are both VB and C# projects that illustrate how you might go about this. The derived PicturePanel
class has properties that allow you to set the bordersize and color as well as the image that is to be
displayed. This sample retrieves the image from an embedded resource. It also uses double bufferring to
minimize flashing as you resize the control.

31.2 How can I copy a bitmap from the clipboard to a PictureBox?

This code snippet shows how you can set your PictureBox's image to be the image from the clipboard:

[C#]
this.pictureBox1.Image = (Bitmap)Clipboard.GetDataObject().GetData(DataFormats.Bitmap);
[VB.Net]
Me.pictureBox1.Image = CType(Clipboard.GetDataObject().GetData(DataFormats.Bitmap), Bitmap)

31.3 How can I copy and paste images/graphs etc from MS Office to a PictureBox?

Since .NET uses it's own format that is not compatible with the EnhancedMetafile format you will have to
use reflection to achieve this. (From a posting in the microsoft.public.dotnet.framework.drawing
newsgroup)

[C#]
using System.Runtime.InteropServices;
using System.Reflection;

public const uint CF_METAFILEPICT = 3;


public const uint CF_ENHMETAFILE = 14;

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]


public static extern bool OpenClipboard(IntPtr hWndNewOwner);

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]


public static extern bool CloseClipboard();

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]


public static extern IntPtr GetClipboardData(uint format);

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]


public static extern bool IsClipboardFormatAvailable(uint format);

//Pasting into PictureBox


if (OpenClipboard(this.Handle))

{
if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
{
IntPtr ptr = GetClipboardData(CF_ENHMETAFILE);
if (!ptr.Equals(new IntPtr(0)))
{
Metafile metafile = new Metafile(ptr,true);
//Set the Image Property of PictureBox
this.pictureBox1.Image = metafile;
}
}
CloseClipboard();
}

31.4 How can I drag and drop an image from one PictureBox to another?

The following code snippet demonstrates how you can drag and copy an image from one picturebox
(Source) another (Target:

[C#]
//In the Form Load
//Set AllowDrop of the Target PictureBox to true as this property cannot be set in the Designer
this.pictureBox2.AllowDrop = true;

//Source PictureBox
private void pictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
pictureBox1.DoDragDrop( pictureBox1.Image, DragDropEffects.All );
}

//Target PictureBox
//Drag Drop Effects
private void pictureBox2_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{

if ( e.Data.GetDataPresent( DataFormats.Bitmap ) )
{
e.Effect = DragDropEffects.Copy;
}
else
e.Effect = DragDropEffects.None;
}

//Set the image to be the dragged image.


private void pictureBox2_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
if ( (e.Data.GetDataPresent(DataFormats.Bitmap)))
{
this.pictureBox1.Image = (Bitmap)(e.Data.GetData(DataFormats.Bitmap));
}
}

[VB.NET]
'In the Form Load
'Set AllowDrop of the Target PictureBox to true as this property cannot be set in the Designer
Me.pictureBox2.AllowDrop = True

'Source PictureBox
Private Sub pictureBox1_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs)
If e.Button = MouseButtons.Left Then
pictureBox1.DoDragDrop(pictureBox1.Image, DragDropEffects.All)
End If
End Sub

'Target PictureBox
'Drag Drop Effects
Private Sub pictureBox2_DragEnter(ByVal sender As Object, ByVal e As
System.Windows.Forms.DragEventArgs)

If e.Data.GetDataPresent(DataFormats.Bitmap) Then
e.Effect = DragDropEffects.Copy
Else
e.Effect = DragDropEffects.None
End If
End Sub

'Set the image to be the dragged image.


Private Sub pictureBox2_DragDrop(ByVal sender As Object, ByVal e As
System.Windows.Forms.DragEventArgs)
If (e.Data.GetDataPresent(DataFormats.Bitmap)) Then
Me.pictureBox1.Image = CType((e.Data.GetData(DataFormats.Bitmap)), Bitmap)
End If
End Sub

© 2001-06 Copyright George Shepherd.

32. Windows Forms Form FAQ Home


32.1 How can I programmatically maximize or minimize a form?
32.2 How can I display a pop up a confirmation dialog when the user closes the form?
32.3 How can I center my form?
32.4 How do I prevent users from resizing a form?
32.5 How do I programmatically set an image as Form's Icon ?
32.6 How can I add items to the System Menu of a form.
32.7 How can I have a form with no title bar, but yet keep the resizing borders?
32.8 I don't want to have the Close box on my form's title bar. How do I remove this system menu box?
32.9 How do I change my application's icon?
32.10 How can I tell if a form is closed from the controlbox (system menu) or from a call to Form.Close?
32.11 I have two forms. How can I access a textbox on one form from the other form?
32.12 How do I create a non-modal top level form that always stays on top of all the app's windows (like
the VS.Net find dialog)?
32.13 How can I display a form that is 'TopMost' for only my application, but not other applications?
32.14 How do I automatically resize the Form when the screen resolution changes between design-time
and runtime?
32.15 How can I ensure that my form will always be on the desktop?
32.16 How can I restrict or control the size of my form?
32.17 How can I prevent a form from being shown in the taskbar?
32.18 How do I prevent a user from moving a form at run time?
32.19 How can I create a non rectangular form?
32.20 How can I make my form cover the whole screen including the TaskBar?
32.21 How can I move a Borderless form?
32.22 How do I force a Windows Form application to exit?
32.23 How do I set the default button for a form?
32.24 How do I get an HWND for a form?
32.25 How can I detect if the user clicks into another window from my modal dialog?
32.26 How do I create a form with no border?
32.27 How do I prevent a Form from closing when the user clicks on the close button on the form's
system menu?
32.28 How do I display a splash screen type form, one with only client area (no border or titlebar)?
32.29 How do I get the window handle (HWND) of my form or control?
32.30 How can I make sure I don't open a second instance modeless dialog that is already opened from
my main form?
32.31 Is there a way to halt a screen from painting until all the controls on the form are initialized?
32.32 How do I return values from a form?
32.33 How can I easily manage whether controls on my form are readonly or not?
32.34 The controls that I've try to add to my form at runtime don't show up. What's wrong?
32.35 Setting Form.Visible to false does not make my main form start up invisibly. How can I make my
main form start up invisibly?
32.36 How to make a form transparent?
32.37 How can I create an instance of a Form class just from knowing its name in a string?

32.1 How can I programmatically maximize or minimize a form?

Use the form's WindowState property.

//minimize
this.WindowState = System.Windows.Forms.FormWindowState.Minimized;

.....

//maximize
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;

32.2 How can I display a pop up a confirmation dialog when the user closes the form?

You can listen to the Form's Closing event, where you can display a MessageBox as show below:

[C#]
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (MessageBox.Show("Do you want to close the application?", "Close Application",
MessageBoxButtons.YesNo) == DialogResult.No)
e.Cancel = true;

}
[VB.NET]
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As
System.ComponentModel.CancelEventArgs)
If MessageBox.Show("Do you want to close the application?","Close
Application",MessageBoxButtons.YesNo) = DialogResult.No Then
e.Cancel = True
End If

End Sub

32.3 How can I center my form?

You can set the Form's StartPosition property to CenterScreen to achieve this.

32.4 How do I prevent users from resizing a form?

You can prevent the users from resizing a form by setting the FormBorderStyle to FixedDialog and setting
the MaximizeBox property to false.

32.5 How do I programmatically set an image as Form's Icon ?

You could do so as shown in the code below :

[C#]
Form form1 = new Form();
Bitmap bmp = imageList1.Images[index] as Bitmap;
form1.Icon = Icon.FromHandle(bmp.GetHicon());

[VB.NET]
Dim form1 As Form = New Form()
Dim bmp As Bitmap = imageList1.Images(index) as Bitmap
form1.Icon = Icon.FromHandle(bmp.GetHicon())

Please refer to the sample attached here that illustrates this.

32.6 How can I add items to the System Menu of a form.

To do this, you can use use iterop to access the GetSystemMenu and AppendMenu Win32 APIs. You also
need to override the form's WndProc method to catch and act on the menu message. This idea was posted in
the Microsoft newsgroups by Lion Shi. Here are some sample projects.
32.7 How can I have a form with no title bar, but yet keep the resizing borders?

Set your form's Text and ControlBox properties.

myForm.Text = "";
myForm.ControlBox = false;

32.8 I don't want to have the Close box on my form's title bar. How do I remove this system menu box?

Set the property Form.ControlBox to false.

32.9 How do I change my application's icon?

In the Solution Explorer window, you'll see a file called app.ico in your project. This file contains your
application icon. You can change this to a different file in the project properties screen which you see by
right-clicking the project node in the Solution Explorer, and selecting Properties..

32.10 How can I tell if a form is closed from the controlbox (system menu) or from a call to Form.Close?

One way to do this is to override the form's WndProc method and check for WM_SYSCOMMAND and
SC_CLOSE. Looking for WM_CLOSE in the override is not sufficient as WM_CLOSE is seen in both
cases. A sample is available for download (C#, VB).

public const int SC_CLOSE = 0xF060;


public const int WM_SYSCOMMAND = 0x0112;

//_closeClick is a bool member of the form initially set false...


// It can be tested in the Closing event to see how the closing came about.

protected override void WndProc(ref System.Windows.Forms.Message m)


{
if(m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
this._closeClick = true;

base.WndProc(ref m);
}

32.11 I have two forms. How can I access a textbox on one form from the other form?
One way to do this is to make the TextBox either a public property or a public field. Then you will be able
to access it through the instance of its parent form. So, if TextBox1 is a public member of FormA and
myFormA is an instance of FormA, then you can use code such as

[VB.NET]
Dim strValue as String = myFormA.TextBox1.Text

[C#]
string strValue = myFormA.TextBox1.Text;

anywhere myFormA is known. Here is a VB project illustrating this technique.

32.12 How do I create a non-modal top level form that always stays on top of all the app's windows (like
the VS.Net find dialog)?

Make your main form the "Owner" of the form in question. Refer to Form.Owner in class reference for
more information.

[C#]
findReplaceDialog.Owner = this; // Your main form.
findReplaceDialog.TopLevel = false;
[VB.Net]
findReplaceDialog.Owner = Me ' Your main form.
findReplaceDialog.TopLevel = False

32.13 How can I display a form that is 'TopMost' for only my application, but not other applications?

You can do this by setting the child form's TopMost to False and setting its Owner property to the Main
Form.

[C#]
Form1 f = new Form1();
f.TopMost = false;
f.Owner = this;
f.Show();

[VB.NET]
dim f as New Form1()
f.TopMost = False
f.Owner = Me
f.Show()
32.14 How do I automatically resize the Form when the screen resolution changes between design-time and
runtime?

The framework automatically resizes the form if the current Font size during runtime is different from the
font size in design-time. It however doesn't auto size when the resolution changes. But it should be easy for
you to accomplish. You could derive a custom Form, provide a "ScreenResolutionBase" property that could
return the current screen resolution (Screen.PrimarScreen.Bounds will give you this). This value will get
serialized in code during design time. Then during runtime in the Form's OnLoad you could check for the
current screen resolution and resize the Form appropriately.

32.15 How can I ensure that my form will always be on the desktop?

To set or control the location of the form using desktop coordinates, you can use the SetDeskTopLocation
property. You can do this by setting the child form's TopMost to False and setting its Owner property to the
Main Form.

[C#]
this.SetDesktopLocation(1,1);

[VB.NET]
Me.SetDesktopLocation(1,1)

32.16 How can I restrict or control the size of my form?

You can restrict the size of a form by setting it's MaximumSize and MinimumSize properties. This will help
you control the maximum and minimum size the form can be resized to. Also note that WindowState
property of the form plays a part in how the form can be resized.

[C#]
//Minimum width = 300, Minimum height= 300
this.MinimumSize = new Size(300, 300);

//Maximum width = 800, Maximum height= unlimited


this.MaximumSize = new Size(800, int.MaxValue);

[VB.NET]
'Minimum width = 300, Minimum height= 300
Me.MinimumSize = New Size(300, 300)

'Maximum width = 800, Maximum height= unlimited


Me.MaximumSize = New Size(800, Integer.MaxValue)
32.17 How can I prevent a form from being shown in the taskbar?

You need to set the form's ShowInTaskbar property to False to prevent it from being displayed in the
Windows taskbar.

[C#]
this.ShowInTaskbar = false;

[VB.NET]
Me.ShowInTaskbar = False

32.18 How do I prevent a user from moving a form at run time?

The following code snippet (posted in the Windows Forms FAQ forums) shows how you can prevent a user
from moving a form at run time:

[C#]
protected override void WndProc(ref Message m)
{
const int WM_NCLBUTTONDOWN = 161;
const int WM_SYSCOMMAND = 274;
const int HTCAPTION = 2;
const int SC_MOVE = 61456;

if((m.Msg == WM_SYSCOMMAND) && (m.WParam.ToInt32() == SC_MOVE))


{
return;
}

if((m.Msg == WM_NCLBUTTONDOWN) && (m.WParam.ToInt32() == HTCAPTION))


{
return;
}

base.WndProc (ref m);


}

[VB.NET]
Protected Overrides Sub WndProc(ByRef m As Message)
const Integer WM_NCLBUTTONDOWN = 161
const Integer WM_SYSCOMMAND = 274
const Integer HTCAPTION = 2
const Integer SC_MOVE = 61456

If (m.Msg = WM_SYSCOMMAND) &&(m.WParam.ToInt32() = SC_MOVE) Then


Return
End If

If (m.Msg = WM_NCLBUTTONDOWN) &&(m.WParam.ToInt32() = HTCAPTION) Then


Return
End If

MyBase.WndProc( m)
End Sub

32.19 How can I create a non rectangular form?

This MSDN article titled Shaped Windows Forms and Controls in Visual Studio .NET shows how you can
create non rectangular forms.

32.20 How can I make my form cover the whole screen including the TaskBar?

The following code snippet demonstrates how you can make your form cover the whole screen including
the Windows Taskbar.

[C#]
// Prevent form from being resized.
this.FormBorderStyle = FormBorderStyle.FixedSingle;
// Get the screen bounds
Rectangle formrect = Screen.GetBounds(this);
// Set the form's location and size
this.Location = formrect.Location;
this.Size = formrect.Size;

[VB.NET]
' Prevent form from being resized.
Me.FormBorderStyle = FormBorderStyle.FixedSingle
' Get the screen bounds
Dim formrect As Rectangle = Screen.GetBounds(Me)
' Set the form's location and size
Me.Location = formrect.Location
Me.Size = formrect.Size
32.21 How can I move a Borderless form?

This code snippet shows how you can move a borderless form.

[C#]
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HTCAPTION = 0x2;
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)


{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
}

32.22 How do I force a Windows Form application to exit?

Your main form is an object of type System.Windows.Forms.Form. Use its Close method to exit the
application. If you wish to Exit from a Form's constructor, this will not work. A workaround is to set a
boolean flag that you can later check in the Form's Load method to call Close if required.

Another way is to use the Application.Exit() method.

32.23 How do I set the default button for a form?

Set the form's AcceptButton property. You can do this either through the designer, or through code such as

Form1.AcceptButton = button1;

32.24 How do I get an HWND for a form?

See the Control.Handle property which returns the HWND. Be careful if you pass this handle to some
Win32 API as Windows Forms controls do their own handle management so they may recreate the handle
which would leave this HWND dangling.
(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

32.25 How can I detect if the user clicks into another window from my modal dialog?

Use the Form.Deactivate event:

this.Deactivate += new EventHandle(OnDeactivate);


//...

private void OnDeactivate(object s, EventArgs e)


{
this.Close();
}

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

32.26 How do I create a form with no border?

Use the Form.FormBorderStyle property to control a form's border.

public void InitMyForm()


{
// Adds a label to the form.
Label label1 = new Label();
label1.Location = new System.Drawing.Point(80,80);
label1.Name = "label1";
label1.Size = new System.Drawing.Size(132,80);
label1.Text = "Start Position Information";
this.Controls.Add(label1);

// Changes the border to Fixed3D.


FormBorderStyle = FormBorderStyle.Fixed3D;

// Displays the border information.


label1.Text = "The border is " + FormBorderStyle;
}

(From the .NET Framework SDK documentation)

32.27 How do I prevent a Form from closing when the user clicks on the close button on the form's system
menu?
Handle the form's Closing event.

private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)


{
if( NotOkToClose() )
e.Cancel = true; //don't close
}

32.28 How do I display a splash screen type form, one with only client area (no border or titlebar)?

You can download a working project that uses this code.

public void CreateMyBorderlessWindow()


{
this.FormBorderStyle = FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.StartPosition = FormStartPosition.CenterScreen;
this.ControlBox = false;
}

32.29 How do I get the window handle (HWND) of my form or control?

Use the Control.Handle property.

32.30 How can I make sure I don't open a second instance modeless dialog that is already opened from my
main form?

One way to do this is to maintain a list of opened modeless dialogs, and check this list before you open a
new one to see if one is already present.

If you open all these modeless dialog's from the same 'main' form, then you can use the OwnedForms
property of that main form to maintain this list of opened dialogs. Below are some code snippets that
suggest how you must go about this. Note that your dialog forms need to be able to turn off the ownership.
This is done below by adding an Owner field to the dialog form.

//sample code that either opens a new dialog or displays an already opened dialog
private void button1_Click(object sender, System.EventArgs e)
{
foreach ( Form f in this.OwnedForms )
{
if (f is Form2)
{
f.Show();
f.Focus();
return;
}
}

//need a new one


Form2 f2 = new Form2();
this.AddOwnedForm(f2);
f2.Owner = this;
f2.Show();
}

//code for form2


public class Form2 : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label1;
public Form Owner;
.......
.......
private void Form2_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
Owner.RemoveOwnedForm(this);
}
}

32.31 Is there a way to halt a screen from painting until all the controls on the form are initialized?

Shawn Burke responded to this question in a posting on microsoft.public.dotnet.framework.windowsforms


newsgroup. There is not currently a way to do this built into the framework, but WM_SETREDRAW will
do what you're looking for. It can't be called recursively, so here's code for a property you can add to your
form to handle it. A VB sample is also available.

int paintFrozen;

private const int WM_SETREDRAW = 0xB;

[DllImport("User32")]
private static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

private bool FreezePainting


{
get { return paintFrozen > 0; }
set {
if (value && IsHandleCreated && this.Visible)
{
if (0 == paintFrozen++)
{
SendMessage(Handle, WM_SETREDRAW, 0, 0);
}
}
if (!value)
{
if (paintFrozen == 0)
{
return;
}

if (0 == --paintFrozen)
{
SendMessage(Handle, WM_SETREDRAW, 1, 0);
Invalidate(true);
}
}
}
}

32.32 How do I return values from a form?

Add public properties to your form. Then these properties can be accessed by any object that creates an
instance of your form.

32.33 How can I easily manage whether controls on my form are readonly or not?

One way is to place all the controls into a single GroupBox and then use the GroupBox.Enabled property to
manage whether the controls are editable or not.

32.34 The controls that I've try to add to my form at runtime don't show up. What's wrong?

Make sure you implemented and executed code similar to the InitializeComponent method that VS adds to
your Windows Forms project for controls added during design time. Recall that InitializeComponent() is
called from your Forms constructor to create the controls, size, position and show the controls, and finally
add the controls to the form's Controls collection. So, your code at runtime should also implement these
same steps. In particular, don't forget the this.Controls.AddRange call that adds your new controls to the
form's Controls collection.

32.35 Setting Form.Visible to false does not make my main form start up invisibly. How can I make my
main form start up invisibly?
This problem is discussed in an article in the .NET docs. Search for "Setting a Form to Be Invisible at Its
Inception". The idea is to startup the application in a different module than your main form. Then the
application and main form can have indiependent lifetimes. Sample code is given in the referenced article.

32.36 How to make a form transparent?

The opacity property enables you to specify a level of transparency for the form and its controls. See the
.NET documentation for Form.Opacity for differences between Opacity and TransparencyKey properties.

Opacity only works with Windows 2000 and later.

32.37 How can I create an instance of a Form class just from knowing its name in a string?

You can use the System.Reflection.Assembly.CreateInstance method to create a form from its name. Below
is a code snippet. The name in the textbox has to be the full name including its namespace. So if there is a
class named Form2 in namespace MyCompanyName, then the textbox would contain
MyCompanyName.Form2. This snippet also assumes that the class is defined in the current executing
assembly. If not, you would have to create an instance of the assembly that contains the class instead of
calling the static method GetExecutingAssembly. As noted on this board, using reflection in this manner
might affect performance.

You can download working samples (VB.NET, C#).

[C#]
try
{
Assembly tempAssembly = Assembly.GetExecutingAssembly();
// if class is located in another DLL or EXE, use something like
// Assembly tempAssembly = Assembly.LoadFrom("myDLL.DLL");
// or
// Assembly tempAssembly = Assembly.LoadFrom("myEXE.exe");

Form frm1 = (Form) tempAssembly.CreateInstance(textBox1.Text);// as Form;


frm1.Show();
}
catch(Exception ex)
{
MessageBox.Show("Error creating: "+ textBox1.Text);
}

[VB.NET]
textBox1.Text = "MyNameSpace.Form2"
......

Try
Dim tempAssembly As System.Reflection.Assembly =
System.Reflection.Assembly.GetExecutingAssembly()

' if class is located in another DLL or EXE, use something like


' tempAssembly = Assembly.LoadFrom("myDLL.DLL")
' or
' tempAssembly = Assembly.LoadFrom("myEXE.exe")

Dim frm1 As Form = CType(tempAssembly.CreateInstance(textBox1.Text), Form) ' as Form;


frm1.Show()
Catch ex As Exception
MessageBox.Show("Error creating: " + ex.ToString())
End Try

© 2001-06 Copyright George Shepherd.

33. Windows Forms CheckedListBox FAQ Home


33.1 How do I check/uncheck all items in my checkedlist?

33.1 How do I check/uncheck all items in my checkedlist?

To check all items, you can use code such as:

C#
for( int i=0 ; i < myCheckedListBox.Items.Count; i++ )
{
myCheckedListBox.SetItemChecked(i, true);
}

VB.NET
Dim i as Integer
For i = 0 To myCheckedListBox.Items.Count - 1
myCheckedListBox.SetItemChecked(i, True)
Next
}
© 2001-06 Copyright George Shepherd.

34. Windows Forms MDI FAQ Home


34.1 How can I create an MDI application in the .NET framework with C#?
34.2 I have an MDI application with several child forms. The child form's Activated event is not being
fired consistently as different child forms are activated. What's wrong?
34.3 In an MDI application, the MDI child's MaximumSize and MinimumSize properties don't seem to
take effect. How can I restrict the size of my MDI child?
34.4 How do I check to see if a child form is already displayed so I don't have two instances showing?
34.5 I need to perform certain custom processing whenever an MDI child form is added to/removed
from the MDIContainer form. How do I determine this?
34.6 How do I paint in my mdi container, a logo, for example?
34.7 How do I make my child Form fill the entire mdi client without being maximized?
34.8 How can I change the background of my MDI Client container?

34.1 How can I create an MDI application in the .NET framework with C#?

This is one of the Quick Start Samples that ships with VS.Net.

34.2 I have an MDI application with several child forms. The child form's Activated event is not being fired
consistently as different child forms are activated. What's wrong?

In .Net 1.0, the child forms do not get the Form.Activated event (only the parent MDI). To catch MDI
children being activated, listen to the Enter/Leave events of that child Form or listen to the
Form.MdiChildActivate event in the parent Form.

In 1.1 the child Forms do get the Activated event.

34.3 In an MDI application, the MDI child's MaximumSize and MinimumSize properties don't seem to take
effect. How can I restrict the size of my MDI child?
It appears that this behavior is a bug that will be corrected in a future .NET release.

You can control the size of your child form by adding a Layout event handler for it. Here is a code snippet
that imposes the minimum size that you set in its properties. You can also handle it by overriding the form's
WndProc method as explained in this Microsoft KB article.

[C#]
private void Document_Layout(object sender, System.Windows.Forms.LayoutEventArgs e)
{
if(this.Bounds.Width < this.MinimumSize.Width)
this.Size = new Size(this.MinimumSize.Width, this.Size.Height);

if(this.Bounds.Height < this.MinimumSize.Height)


this.Size = new Size(this.Size.Width, this.MinimumSize.Height);
}

[VB.NET]
Private Sub Document_Layout(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.LayoutEventArgs) Handles MyBase.Layout

If (Me.Bounds.Width < Me.MinimumSize.Width) Then


Me.Size = New Size(Me.MinimumSize.Width, Me.Size.Height)
End If

If (Me.Bounds.Height < Me.MinimumSize.Height) Then


Me.Size = New Size(Me.Size.Width, Me.MinimumSize.Height)
End If
End Sub

34.4 How do I check to see if a child form is already displayed so I don't have two instances showing?

Here are two ways you can do this.

i) Within the parent MDI form, use code such as this:

// MyChildForm is the one I'm looking for


MyChildForm childForm = null;
foreach(Form f in this.MdiChildren)
{
if(f is MyChildForm)
{
// found it
childForm = (MyChildForm) f;
break;
}
}
if( childForm != null)
{
childForm.Show();
childForm.Focus();
}
else
{
childForm = new MyChildForm();
childForm.MdiParent = this;
childForm.Show();
childForm.Focus();
}

ii) Here is a second solution suggested by John Conwell that implements a singleton pattern on the child
form.

In the MDI Child form put this code in (where frmChildForm is the MDI child form you want to control)

//Used for singleton pattern


static frmChildForm childForm;
public static ChildForm GetInstance
{
if (childForm == null)
childForm = new frmChildForm;
return childForm;
}

In the Parent MDI form use the following code to call the child MDI form

frmChildForm childForm = frmChildForm.GetInstance();


childForm.MdiParent = this;
childForm.Show();
childForm.BringToFront();

The first time this code is called, the static GetInstance method will create and return an instance of the
child form. Every other time this code is called, the GetInstance method will return the existing instance of
the child from, stored in the static field childForm. If the child form instance is ever destroyed, the next
time you call GetInstance, a new instance will be created and then used for its lifetime.

Also, if you need constructors or even overloaded constructors for your MDI Child Form, just add the
needed parameters to the GetInstance function and pass them along to the class constructor.

34.5 I need to perform certain custom processing whenever an MDI child form is added to/removed from
the MDIContainer form. How do I determine this?
MDIContainer forms have an MDIClient child window and it is to this MDIClient window that MDI child
forms are parented. The MDIClient's ControlAdded/ControlRemoved events will be fired whenever a child
form is added or removed. You can subscribe to these events and add the required processing code from
within the handlers.

// From within the MDIContainer form, subscribe to the MDIClient's ControlAdded/ControlRemoved


events
foreach(Control ctrl in this.Controls)
{
if(ctrl.GetType() == typeof(MdiClient))
{
ctrl.ControlAdded += new ControlEventHandler(this.MDIClient_ControlAdded);
ctrl.ControlRemoved += new ControlEventHandler(this.MDIClient_ControlRemoved);
break;
}
}

protected void MDIClient_ControlAdded(object sender, ControlEventArgs e)


{
Form childform = e.Control as Form;
Trace.WriteLine(String.Concat(childform.Text, " - MDI child form was added."));
}

protected void MDIClient_ControlRemoved(object sender, ControlEventArgs e)


{
Trace.WriteLine(String.Concat(e.Control.Text, " - MDI child form was removed."));
}

34.6 How do I paint in my mdi container, a logo, for example?

You should not try listening to your MDI container Form's Paint event, instead listen to the Paint event of
the MDIClient control that is a child of the mdi container form. This article provides you a detailed
example: Painting in the MDI Client Area

34.7 How do I make my child Form fill the entire mdi client without being maximized?

Here is how it can be done. This takes into account all docked controls (including menus) in the mdi parent
form.

[C#]
private void FillActiveChildFormToClient()
{
Form child = this.ActiveMdiChild;
Rectangle mdiClientArea = Rectangle.Empty;
foreach(Control c in this.Controls)
{
if(c is MdiClient)
mdiClientArea = c.ClientRectangle;
}
child.Bounds = mdiClientArea;
}

[VB.Net]
Private Sub FillActiveChildFormToClient()
Dim child As Form = Me.ActiveMdiChild
Dim mdiClientArea As Rectangle = Rectangle.Empty
Dim c As Control
For Each c In Me.Controls
If TypeOf c Is MdiClient Then
mdiClientArea = c.ClientRectangle
End If
Next
child.Bounds = mdiClientArea
End Sub

34.8 How can I change the background of my MDI Client container?

The default behavior is to make the client container use the Control color from the Control panel. You can
change this behavior by making the MDI Client container use the form's BackColor and Image. To do this,
after the call to InitializeComponents(), add the code below. You can also download a working MDI Client
project that has this code in it.

//set back color


foreach(Control c in this.Controls)
{
if(c is MdiClient)
{
c.BackColor = this.BackColor;
c.BackgroundImage = this.BackgroundImage;
}
}
© 2001-06 Copyright George Shepherd.

35. Windows Forms In IE FAQ Home


35.1 Where can I get information on hosting Windows Forms Controls in IE?
35.2 How do I clear the download cache in my client machine?
35.3 How can I use a WinForms Control in IE?
35.4 What are some common gotchas while trying to embed a Windows Forms Control in IE?
35.5 What are some common UI limitations while running code in the Internet Zone?

35.1 Where can I get information on hosting Windows Forms Controls in IE?

These articles should give you some introduction to hosting WinForms Controls in IE: Using Windows
Forms Controls in Internet Explorer Host Secure, Lightweight Client-Side Controls in Microsoft Internet
Explorer

35.2 How do I clear the download cache in my client machine?

The following command line will do the trick:

gacutil /cdl

35.3 How can I use a WinForms Control in IE?

You cannot use a WinForms Control directly in IE, you will have to instead derive from it and then use the
derived instance from a custom assembly.

35.4 What are some common gotchas while trying to embed a Windows Forms Control in IE?

The issues listed here are pertaining to code running in IE in the default Internet Zone.

1) You cannot view Controls inside IE using the 1.0 framework (when running with the permissions in the
default Internet Zone). This is however possible with the 1.1 (Everett) framework.
2) Use only one . in the assembly file name and "Assembly Name"(in Project Properties Dialog). For
example, "Syncfusion.Shared.dll" is an invalid dll name, but "Shared.dll" is valid.

3) Signed assemblies couldn't be loaded.

35.5 What are some common UI limitations while running code in the Internet Zone?

1) Cannot override methods like WndProc, ProcessCmdKey, etc in a derived Control. The class ref for a
particular property will let you know about the permission requirements.

2) Cannot call Control.Parent.

3) Cannot call Control.Focus() method.

36. Windows Forms Smart Client FAQ Home


36.1 Where are the getting started info. on Smart Client Deployment?

36.1 Where are the getting started info. on Smart Client Deployment?

Here is some information (provided by Lubos in the newsgroups):


http://www.fawcette.com/vsm/2002_09/magazine/columns/desktopdeveloper/
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnadvnet/html/vbnet10142001.asp
http://msdn.microsoft.com/msdnmag/issues/02/07/NetSmartClients/default.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnforms/html/winforms11122002.asp

37. GDI+ Bitmaps & Images FAQ Home


37.1 How do I create a "Negative" representation of my image?
37.2 How do I programmatically load, modify and save a bitmap?
37.3 How do I draw an image with a gray scale?
37.4 How do I draw my bitmap in a disabled state?
37.5 How can I programmatically create a bitmap?
37.6 How can I swap colors in a bitmap or icon?
37.7 How do I create a new image off a base image with certain portions of the base image modified, in
code?
37.8 How do I extract a Bitmap from an icon of a specific size?
37.9 How to draw a shadow for a given transparent image?
37.10 How to draw a faded image?
37.11 How do I overlay one bitmap over another?
37.12 How do I get the color of a pixel in my bitmap?
37.13 How do I capture a bitmap of my form?
37.14 How can I create a thumbnail of a bitmap?
37.15 How do I create a new bitmap with a new size based on an existing bitmap?
37.16 How can I read individual frames from an animated image?

37.1 How do I create a "Negative" representation of my image?

This is quite simple actually. All you need to do is determine the color of a given pixel, and then subtract
the RGB values from 255 (the maximum) and then reset the pixel.

Here is the pertinent code.

[Code - C#]

for(int x = 0; x < mybitmap.Width; x++)


{
for(int y = 0; y < mybitmap.Height; y++)
{
//get the current color of the pixel
System.Drawing.Color c = mybitmap.GetPixel(x,y);

mybitmap.SetPixel(x,y, System.Drawing.Color.FromArgb(255 - c.R, 255 - c.G, 255 - c.B));


}
}

Note: This modifies the existing image, so work on a copy if you want to maintain the original.

37.2 How do I programmatically load, modify and save a bitmap?

You can download a working project. Below are VB code snippets showing how you might do these tasks.

'load a bitmap from an embedded resource


Dim Bmp As Bitmap
' from an embbedded resource
Dim curName As String = "BitmapVB.sync.bmp"
Dim strm As System.IO.Stream = Me.GetType().Assembly.GetManifestResourceStream(curName)
Bmp = New Bitmap(strm)
PictureBox1.Image = Bmp
.....
.....
'load a bitmap from a file
Dim Bmp As Bitmap = Image.FromFile("c:\sync.bmp")
PictureBox1.Image = Bmp
.....
.....
'modify a bitmap
Dim Bmp As Bitmap = PictureBox1.Image.Clone
Dim g As Graphics = Graphics.FromImage(Bmp)
Dim brush1 As SolidBrush = New SolidBrush(Color.Red)
g.DrawString(TextBox1.Text, TextBox1.Font, brush1, 10, 10)
PictureBox2.Image = Bmp
g.Dispose()
....
....
'save a bitmap as a file
Dim dlg As SaveFileDialog = New SaveFileDialog()
dlg.Title = "Save BMP file"
dlg.InitialDirectory = "c:\"
dlg.Filter = "bmp files (*.bmp)|*.bmp|All files (*.*)|*.*"
If dlg.ShowDialog = DialogResult.OK Then
PictureBox2.Image.Save(dlg.FileName
End If

37.3 How do I draw an image with a gray scale?

Here is some code:

// Not the closest grayscale representation in the RGB space, but


// pretty close.
// Closest would be the cubic root of the product of the RGB colors,
// but that cannot be represented in a ColorMatrix.
public void DrawGrayedImage(Graphics g, Image image, int left,
int top)
{
ImageAttributes ia = new ImageAttributes();
ColorMatrix cm = new ColorMatrix();

// 1/3 on the top 3 rows and 3 columns


cm.Matrix00 = 1/3f;
cm.Matrix01 = 1/3f;
cm.Matrix02 = 1/3f;
cm.Matrix10 = 1/3f;
cm.Matrix11 = 1/3f;
cm.Matrix12 = 1/3f;
cm.Matrix20 = 1/3f;
cm.Matrix21 = 1/3f;
cm.Matrix22 = 1/3f;

ia.SetColorMatrix(cm);

g.DrawImage(image, new Rectangle(left, top, image.Width,


image.Height), 0, 0, image.Width, image.Height,
GraphicsUnit.Pixel, ia);
}
37.4 How do I draw my bitmap in a disabled state?

Use the DrawImageDisabled method of the ControlPaint class.

37.5 How can I programmatically create a bitmap?

Since .NET uses it's own format that is not compatible with the EnhancedMetafile format you will have to
use reflection to achieve this. (From a posting in the microsoft.public.dotnet.framework.drawing
newsgroup)

[C#]
using System.Runtime.InteropServices;
using System.Reflection;

public const uint CF_METAFILEPICT = 3;


public const uint CF_ENHMETAFILE = 14;

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]


public static extern bool OpenClipboard(IntPtr hWndNewOwner);

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]


public static extern bool CloseClipboard();

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]


public static extern IntPtr GetClipboardData(uint format);

[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]


public static extern bool IsClipboardFormatAvailable(uint format);

//Pasting into PictureBox


if (OpenClipboard(this.Handle))

{
if (IsClipboardFormatAvailable(CF_ENHMETAFILE))
{
IntPtr ptr = GetClipboardData(CF_ENHMETAFILE);
if (!ptr.Equals(new IntPtr(0)))
{
Metafile metafile = new Metafile(ptr,true);
//Set the Image Property of PictureBox
this.pictureBox1.Image = metafile;
}
}
CloseClipboard();
}

37.6 How can I swap colors in a bitmap or icon?

You use ImageAttributes, adding a ColorMap that swaps the colors. Here is a code snippet.

Bitmap originalBMP = (Bitmap) Image.FromFile(@"c:\circle.bmp");

//make a copy so original will still be available


Bitmap swappedBMP = new Bitmap(originalBMP);

Graphics g = Graphics.FromImage(swappedBMP);

// Create a color map.


ColorMap[] colorSwapper= new ColorMap[2];
colorSwapper[0] = new ColorMap();
colorSwapper[1] = new ColorMap();
colorSwapper[0].OldColor = Color.Red; //red changes to yellow
colorSwapper[0].NewColor = Color.Yellow;
colorSwapper[1].OldColor = Color.Blue;//blue changes to green
colorSwapper[1].NewColor = Color.Green;

// Create an ImageAttributes object, and call SetRemapTable


ImageAttributes imageAttr = new ImageAttributes();
imageAttr.SetRemapTable(colorSwapper);

//overdraw the bitmap with swapped colors


g.DrawImage(swappedBMP, new Rectangle(0, 0,
swappedBMP.Width, swappedBMP.Height),0, 0, swappedBMP.Width,
swappedBMP.Height, GraphicsUnit.Pixel, imageAttr);

pictureBox1.Image = swappedBMP;

Here is similar code that wraps this technique in a method that swaps a single color.

protected void DrawMyBitmap(Graphics gph, Color oldColor, Color newColor, Bitmap baseImage,
Rectangle rect)
{
ImageAttributes imgattr = new ImageAttributes();
ColorMap[] clrmap = new ColorMap[1]{ new ColorMap() };

clrmap[0].OldColor = oldColor;
clrmap[0].NewColor = newColor;
imgattr.SetRemapTable(clrmap);

gph.DrawImage(baseImage,rect,0,0,rect.Width, rect.Height,GraphicsUnit.Pixel,imgattr);
}

37.7 How do I create a new image off a base image with certain portions of the base image modified, in
code?

This code depends on the actual bitmap in use. This logic sets a random rectangular portion in the image to
a new color.

public class ImageUtil


{
private Image baseImage;

private void InitBaseImage(Image baseImage)


{
this.baseImage = baseImage.Clone() as Image;
}

private Image ApplyNewColorOnImage(Color newColor)


{
// Create a new bitmap off the base image.
Image newImage = this.baseImage.Clone() as Image;
Bitmap newBitmap = new Bitmap(newImage);

// Set the Color cue pixels to the appropriate color.


// This logic of course, depends on the actual bitmap.
for(int i = 12; i <= 14; i++)
for(int j = 2; j <= 14; j++)
newBitmap.SetPixel(j, i, newColor);

return newImage;
}
}

37.8 How do I extract a Bitmap from an icon of a specific size?

Icon icoClose;

// Initialize this icoClose from the resource (for example). Code omitted.
… … …
// Now create a new icon off this base icon with the required size (18 X 18) in this case.
Icon icoClose18By18 = new Icon(icoClose, 18, 18);
// Create a bitmap off this icon.
Bitmap bmpClose = icoClose.ToBitmap();

37.9 How to draw a shadow for a given transparent image?

The following method will draw a shadow of the supplied image at the specifed location.

The general usage pattern is to call this method first to draw a shadow at a (2,2) offset from where the
original image will be drawn and then draw the original image itself.

public static void DrawShadow(Graphics g, Image iconImage, int left, int top)
{
ImageAttributes ia = new ImageAttributes();
ColorMatrix cm = new ColorMatrix();

cm.Matrix00 = 0;
cm.Matrix11 = 0;
cm.Matrix22 = 0;
cm.Matrix33 = 0.25f;

ia.SetColorMatrix(cm);

g.DrawImage(iconImage, new Rectangle(left, top, iconImage.Width,


iconImage.Height), 0, 0, iconImage.Width, iconImage.Height,
GraphicsUnit.Pixel, ia);
}

37.10 How to draw a faded image?

The trick is to use an alpha component while drawing the image.

// transparancy should be in the range 0 to 1


protected void DrawScrollImage(Graphics g, Rectangle rect, Image image, float transparancy)
{
ImageAttributes ia = new ImageAttributes();
ColorMatrix cm = new ColorMatrix();
cm.Matrix00 = 1;
cm.Matrix11 = 1;
cm.Matrix22 = 1;
cm.Matrix33 = transparancy;

ia.SetColorMatrix(cm);
g.DrawImage(image, rect, 0, 0, image.Width, image.Height,
GraphicsUnit.Pixel, ia);
}

37.11 How do I overlay one bitmap over another?

You can create a Graphics object from the base bitmap, and then use this Graphics object to draw the
second bitmap with a transparent color that allows the base bitmap to show thorugh.

Bitmap Circle = (Bitmap)Image.FromFile(@"c:\circle.bmp");


Bitmap MergedBMP = (Bitmap)Image.FromFile(@"c:\cross.bmp");
Graphics g = Graphics.FromImage(Circle);
MergedBMP.MakeTransparent(Color.White);
g.DrawImage(MergedBMP,0,0);
g.Dispose();

pictureBox1.Image = Circle;

37.12 How do I get the color of a pixel in my bitmap?

Use the Bitmap.GetPixel method.

[C#]
Color c = myBitmap.GetPixel( xPos, yPos);

[VB.NET}
Dim c as Color = myBitmap.GetPixel( xPos, yPos)

37.13 How do I capture a bitmap of my form?

You can import the BitBlt API to handle this problem. Here is a solution offered by Simon Murrell and
Lion Shi in the microsoft.public.dotnet.windows.forms newsgroup. The number used below, 13369376, is
Int32 SRCCOPY = 0xCC0020;
You can use Gdi32 dll. You can define the BitBlt method found within the Gdi32 dll with the code below.

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
private static extern bool BitBlt(
ntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
System.Int32 dwRop // raster operation code
);

And you can then use the copy below in a button click event to save the form to an image.

Graphics g1 = this.CreateGraphics();
Image MyImage = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, g1);
Graphics g2 = Graphics.FromImage(MyImage);
IntPtr dc1 = g1.GetHdc();
IntPtr dc2 = g2.GetHdc();
BitBlt(dc2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, dc1, 0, 0, 13369376);
g1.ReleaseHdc(dc1);
g2.ReleaseHdc(dc2);
MyImage.Save(@"c:\Captured.bmp", ImageFormat.Bmp);

You will need to use the System.Drawing.Imaging namespace.

Here is VB code posted by Armin Zingler in the microsoft.public.dotnet.languages.vb newsgroup.

Public Class Win32

Public Declare Function BitBlt Lib "gdi32" Alias "BitBlt" _


(ByVal hDestDC As Integer, ByVal x As Integer, _
ByVal y As Integer, ByVal nWidth As Integer, _
ByVal nHeight As Integer, ByVal hSrcDC As Integer, _
ByVal xSrc As Integer, ByVal ySrc As Integer, _
ByVal dwRop As Integer) As Integer

Public Declare Function GetWindowDC Lib "user32" Alias "GetWindowDC" _


(ByVal hwnd As Integer) As Integer

Public Declare Function ReleaseDC Lib "user32" Alias "ReleaseDC" _


(ByVal hwnd As Integer, ByVal hdc As Integer) As Integer

Public Const SRCCOPY As Integer = &HCC0020


End Class

Public Class Hardcopy

Public Shared Function CreateBitmap( _


ByVal Control As Control) _
As Bitmap

Dim gDest As Graphics


Dim hdcDest As IntPtr
Dim hdcSrc As Integer
Dim hWnd As Integer = Control.Handle.ToInt32

CreateBitmap = New Bitmap(Control.Width, Control.Height)


gDest = gDest.FromImage(CreateBitmap)

hdcSrc = Win32.GetWindowDC(hWnd)
hdcDest = gDest.GetHdc

Win32.BitBlt( _
hdcDest.ToInt32, 0, 0, Control.Width, Control.Height, _
hdcSrc, 0, 0, Win32.SRCCOPY _
)

gDest.ReleaseHdc(hdcDest)
Win32.ReleaseDC(hWnd, hdcSrc)

End Function

End Class

'In your Form:

Private Sub Button1_Click( _


ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click

Dim bmp As Bitmap

bmp = Hardcopy.CreateBitmap(Me)
bmp.Save("c:\test.bmp")

End Sub

37.14 How can I create a thumbnail of a bitmap?


You can use the GetThumbnailImage method to generate and display a thumbnail of a bitmap as shown
below:

[C#]

public bool ThumbnailCallback()


{
return false;
}

//Generate a thumbnail of the bitmap and display it in a PictureBox

Image.GetThumbnailImageAbort myCallback =
new Image.GetThumbnailImageAbort(ThumbnailCallback);
Bitmap myBitmap = new Bitmap("C:\\images\\MyBitMap.bmp");
this.pictureBox1.Image = (Bitmap) myBitmap.GetThumbnailImage(150,75,myCallback, IntPtr.Zero);

37.15 How do I create a new bitmap with a new size based on an existing bitmap?

You can simply specify the new size in the Bitmap constructr as follows:

[C#]
Bitmap bmp = new Bitmap("exisiting.bmp");
// Create a new bitmap half the size:
Bitmap bmp2 = new Bitmap(bmp, bmp.Width*0.5, bmp.Height*0.5);
this.BackgroundImage = bmp2;

[VB.Net]
Dim bmp As New Bitmap( "exisiting.bmp")
' Create a new bitmap half the size:
Dim bmp2 As New Bitmap( bmp, bmp.Width * 0.5, bmp.Height * 0.5)
Me.BackgroundImage = bmp2

If you have to specify a particular Interpolation mode while resizing use the following code:

[C#]
Bitmap bmp = new Bitmap("exisiting.bmp");
// Create a new bitmap half the size:
Bitmap bmp2 = new Bitmap( bmp.Width*0.5, bmp.Height*0.5, Imaging.PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(bmp2);

// Set interpolation mode


g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

// Draw image using specified interpolation mode.


g.DrawImage(bmp, 0, 0, bmp2.Width, bmp2.Height);
this.BackgroundImage = bmp2

[VB.Net]
Dim bmp As New Bitmap( "existing.bmp")
Dim bmp2 As New Bitmap( bmp.Width * 0.5, bmp.Height * 0.5, Imaging.PixelFormat.Format24bppRgb)
Dim g As Graphics = Graphics.FromImage(bmp2)

' Set interpolation mode


g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic

' Draw image using specified interpolation mode.


g.DrawImage(bmp, 0, 0, bmp2.Width, bmp2.Height)
Me.BackgroundImage = bmp2

37.16 How can I read individual frames from an animated image?

GDI+ has direct support for reading and outputting animated images.

To get at the individual frames, you can use the image's FrameDimensionList, and then call
SelectActiveFrame, by passing in the dimension and the zero based frame index.

First, create a new FrameDimension object:

FrameDimension dimension = new


System.Drawing.Imaging.FrameDimension(myImage.FrameDimensionsList[0]);

Once you have the dimension, you can get the frame count:

int frameCount = myImage.GetFrameCount(dimension);

Now, that you know the frame count of the image, you can call SelectActiveFrame by passing in the
dimension and the frame index (zero based).

myImage.SelectActiveFrame(dimension,1);
If the image is being viewed at runtime, then the call to SelectActiveFrame will set the current frame, and
then begin to loop through again (unless it is a jpeg image). The attached sample works around this by
saving the image to a MemoryStream for display - thereby capturing the one frame that is chosen.

Sample Application w/Source Code C# or VB

38. GDI+ Fonts FAQ Home


38.1 How do I set the font for a control?
38.2 When I try to set a particular font style, say italics, I get an error message "Property cannot be
assigned to -- it is read only". How can I set this read only property?
38.3 How can I draw font samples from the available fonts?
38.4 MeasureString seems to have problems with white space and punctuation. Is there a better method
to use?
38.5 How can I draw a single line of text with different fonts using DrawString?
38.6 How do I display adjacent text?
38.7 How can I fill a combobox with available fonts?

38.1 How do I set the font for a control?

Use the Font property for the control along with the Font class in the System.Drawing class.

button1.Font = new Font ("Courier", 10, FontStyle.Bold);

38.2 When I try to set a particular font style, say italics, I get an error message "Property cannot be
assigned to -- it is read only". How can I set this read only property?

Code such as

tabControl1.Font.Italic = true;

will not work. Instead, you have to create a new Font object, and set the property during its creation. This
code will work.

tabControl1.Font = new Font(tabControl1.Font, FontStyle.Italic);

38.3 How can I draw font samples from the available fonts?
James DeBroeck of Microsoft gave this response on the microsoft.public.dotnet.framework.windowsforms.

Here is some C# OnPaint code that will show you how to use FontFamily to get a list of fonts:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)


{
int i, nCount;
SolidBrush b = new SolidBrush( Color.Black );
int x = 0, y = 0;

nCount = FontFamily.Families.Length;

for(i=0;i
{
FontStyle fs = FontStyle.Regular;
Font f;
String StylesDesc = "";

if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Regular))
StylesDesc += "Regular ";
else
fs = FontStyle.Italic;

if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Italic))
StylesDesc += "Italic ";
else
fs = FontStyle.Bold;

if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Bold))
StylesDesc += "Bold ";

if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Underline))
StylesDesc += "Underline ";

if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Strikeout))
StylesDesc += "Strikeout ";

if (StylesDesc.Length > 0)
StylesDesc = StylesDesc.Substring(0,StylesDesc.Length-1);

f = new Font( FontFamily.Families[i].Name, 12, fs);

String s = FontFamily.Families[i].Name + " " + StylesDesc;


e.Graphics.DrawString( s, f, b, x, y );
y += f.Height;

}
}
38.4 MeasureString seems to have problems with white space and punctuation. Is there a better method to
use?

Try calling one of the overloads of MeasureString that takes an StringFormat parameter and pass it
StringFormat.GenericTypographic. Here is some code that shows the same string and font giving different
results depending upon the StringFormat parameter.

StringFormat sf = new StringFormat(StringFormat.GenericTypographic);

SizeF size = e.Graphics.MeasureString("this has some words", Font, 500, sf);


SizeF size1 = e.Graphics.MeasureString("this has some words", Font);
string s = string.Format("GenericTypographic={0:f2} GenericDefault={1:f2}", size.Width, size1.Width);
MessageBox.Show(s);

38.5 How can I draw a single line of text with different fonts using DrawString?

The key is that you have to calculate the ascent height of the font. The font ascent as reported by
FontFamily.GetCellAscent is in what is called 'Design Units'. The Cell Spacing design unit value of fonts is
proportional to the actual height of the font on the device. We use this relationship to calculate cell ascent in
device units.

The rendering code has to just ensure that the x, y position passed to DrawString takes care of the ascent.

private void HandlePaint(object sender, PaintEventArgs args)


{
// clear the background
Graphics g = args.Graphics;
g.Clear(Color.AliceBlue);

// create a pen
Pen pen = new Pen(Color.Red, 1f);

// the string to be drawn


string s = "Side by side";

// the first font


Font f1 = new Font("Arial", 10f);
float strWidth1 = g.MeasureString(s, f1).Width;
float fontHeight1 = f1.GetHeight(g);
float fontAscentHeight1 =
(fontHeight1/f1.FontFamily.GetLineSpacing(f1.Style))*f1.FontFamily.GetCellAscent(f1.Style);

// the second font


Font f2 = new Font("Times New Roman", 48);
float fontHeight2 = f2.GetHeight(g);
float fontAscentHeight2 =
(fontHeight2/f2.FontFamily.GetLineSpacing(f2.Style))*f2.FontFamily.GetCellAscent(f2.Style);

// draw the base line


Point ptStart = new Point(0, this.ClientSize.Height/2);
Point ptEnd = new Point(this.ClientSize.Width, this.ClientSize.Height/2);
g.DrawLine(Pens.Black, ptStart, ptEnd);

// draw string with first font


g.DrawString(s, f1, Brushes.Red, new PointF(0, ptStart.Y - fontAscentHeight1));
// draw string with second font
g.DrawString(s, f2, Brushes.Red, new PointF(strWidth1, ptStart.Y - fontAscentHeight2));
}

38.6 How do I display adjacent text?

Check out this article by David C. Brown of the Windows Forms team at windowsforms.net. It discusses
several reasons why you GDI+ output may lok differently that GDI output. One of the topics discussed is
how to draw adjacent text.

38.7 How can I fill a combobox with available fonts?

Try

comboBox1.Items.AddRange(FontFamily.Families);

39. GDI+Colors FAQ Home


39.1 I need to save a color as a string and be able to retrieve it. How can I do this?
39.2 How do I convert a color to integer and vice-versa?
39.3 How do I desaturate a specific color?
39.4 How do you translate a HSB color to RGB?
39.5 Is there a way to force some contrast between two colors (like background color and foreground
color)?
39.6 What is alpha blending?
39.7 Is there a way to find out the brightness of a Color?
39.8 How can a translate an OLE_COLOR into a GDI+ Color object?

39.1 I need to save a color as a string and be able to retrieve it. How can I do this?
Here are a couple of routines that might do what you want. ColorToString takes a color and represents it as
a string that then can be passed into its companion StringToColor routine that will take the string back into
a color. I think it works with all types of colors. You can download a test project.

public string ColorToString(Color c)


{
string s = c.ToString();
s = s.Split(new char[]{'[',']'})[1];
string[] strings = s.Split(new char[]{'=',','});
if(strings.GetLength(0) > 7)
{
s = strings[1] + "," + strings[3] + "," + strings[5] + "," + strings[7];
}
return s;
}

public Color StringToColor(string s)


{
return (Color)TypeDescriptor.GetConverter(typeof(Color)).ConvertFromString(s);
}

39.2 How do I convert a color to integer and vice-versa?

You can do it using the FromArgb and ToArgb methods as follows:

// from Color to int


int blueInt = Color.Blue.ToArgb( );

// from int to Color


Color newColor = Color.FromArgb( blueInt );

39.3 How do I desaturate a specific color?

Jon Skeet provided this solution in the MS Windows Forms News Group.

[C#]
double greyLevel = original.R*0.299 + original.G*0.587 + original.B*0.144;
if (greyLevel > 255)
{
greyLevel = 255;
}
Color desaturated = new Color.FromArgb((byte) greyLevel, (byte)greyLevel, (byte)greyLevel);

[VB.NET]
Dim greyLevel As Double = original.R * 0.299 + original.G * 0.587 + original.B * 0.144
If greyLevel > 255 Then
greyLevel = 255
End If

Dim desaturated As New Color.FromArgb(CByte(greyLevel), CByte(greyLevel), CByte(greyLevel))

39.4 How do you translate a HSB color to RGB?

Here is a routine that does this. Note that the conversion is not precise but very close. (Please do post any
better algorithm in our forums).

[C#]
// This does not seem to yield accurate results, but very close.
public static void ConvertHSBToRGB(float h, float s, float v, out float r, out float g, out float b)
{
if (s == 0f)
{
// if s = 0 then h is undefined
r = v;
g = v;
b = v;
}
else
{
float hue = (float)h;
if (h == 360.0f)
{
hue = 0.0f;
}
hue /= 60.0f;
int i = (int)Math.Floor((double)hue);
float f = hue - i;
float p = v * (1.0f - s);
float q = v * (1.0f - (s * f));
float t = v * (1.0f - (s * (1 - f)));

switch(i)
{
case 0: r = v; g = t; b = p; break;
case 1: r = q; g = v; b = p; break;
case 2: r = p; g = v; b = t; break;
case 3: r = p; g = q; b = v; break;
case 4: r = t; g = p; b = v; break;
case 5: r = v; g = p; b = q; break;

default: r = 0.0f; g = 0.0f; b = 0.0f; break; /*Trace.Assert(false);*/ // hue out of range


}
}
}
[VB.Net]
Public Shared Sub ConvertHSBToRGB(h As Single, s As Single, v As Single, ByRef r As Single, ByRef g
As Single, ByRef b As Single)
If s = 0F Then
' if s = 0 then h is undefined
r=v
g=v
b=v
Else
Dim hue As Single = System.Convert.ToSingle(h)
If h = 360F Then
hue = 0F
End If
hue /= 60F
Dim i As Integer = Fix(Math.Floor(System.Convert.ToDouble(hue)))
Dim f As Single = hue - i
Dim p As Single = v *(1F - s)
Dim q As Single = v *(1F - s * f)
Dim t As Single = v *(1F - s *(1 - f))

Select Case i
Case 0
r=v
g=t
b=p
Case 1
r=q
g=v
b=p
Case 2
r=p
g=v
b=t
Case 3
r=p
g=q
b=v
Case 4
r=t
g=p
b=v
Case 5
r=v
g=p
b=q

Case Else
r = 0F
g = 0F
b = 0F 'Trace.Assert(false);
' hue out of range
End Select
End If
End Sub 'ConvertHSBToRGB

39.5 Is there a way to force some contrast between two colors (like background color and foreground
color)?

Here is a routine that will let you do this. The code below uses the routine from our previous faq (how to
translate a HSB color to RGB color).

[C#]
///
/// Adjusts the specified Fore Color's brightness based on the specified back color and preferred
contrast.
///
/// The fore Color to adjust.
/// The back Color for reference.
/// Preferred contrast level.
///
/// This method checks if the current contrast in brightness between the 2 colors is
/// less than the specified contrast level. If so, it brigtens or darkens the fore color appropriately.
///
public static void AdjustForeColorBrightnessForBackColor(ref Color foreColor, Color backColor,
float prefContrastLevel)
{
float fBrightness = foreColor.GetBrightness();
float bBrightness = backColor.GetBrightness();

float curContrast = fBrightness - bBrightness;


float delta = prefContrastLevel - (float)Math.Abs(curContrast);

if((float)Math.Abs(curContrast) < prefContrastLevel)


{
if(bBrightness < 0.5f)
{
fBrightness = bBrightness + prefContrastLevel;
if(fBrightness > 1.0f)
fBrightness = 1.0f;
}
else
{
fBrightness = bBrightness - prefContrastLevel;
if(fBrightness < 0.0f)
fBrightness = 0.0f;
}

float newr, newg, newb;


ConvertHSBToRGB(foreColor.GetHue(), foreColor.GetSaturation(), fBrightness, out newr,
out newg, out newb);

foreColor = Color.FromArgb(foreColor.A, (int)Math.Floor(newr * 255f),


(int)Math.Floor(newg * 255f),
(int)Math.Floor(newb * 255f));
}
}
[VB.Net]
'/
'/ Adjusts the specified Fore Color's brightness based on the specified back color and preferred contrast.
'/
'/ The fore Color to adjust.
'/ The back Color for reference.
'/ Preferred contrast level.
'/
'/ This method checks if the current contrast in brightness between the 2 colors is
'/ less than the specified contrast level. If so, it brigtens or darkens the fore color appropriately.
'/
Public Shared Sub AdjustForeColorBrightnessForBackColor(ByRef foreColor As Color, backColor As
Color, prefContrastLevel As Single)
Dim fBrightness As Single = foreColor.GetBrightness()
Dim bBrightness As Single = backColor.GetBrightness()

Dim curContrast As Single = fBrightness - bBrightness


Dim delta As Single = prefContrastLevel - System.Convert.ToSingle(Math.Abs(curContrast))

If System.Convert.ToSingle(Math.Abs(curContrast)) < prefContrastLevel Then


If bBrightness < 0.5F Then
fBrightness = bBrightness + prefContrastLevel
If fBrightness > 1F Then
fBrightness = 1F
End If
Else
fBrightness = bBrightness - prefContrastLevel
If fBrightness < 0F Then
fBrightness = 0F
End If
End If
Dim newr, newg, newb As Single
ConvertHSBToRGB(foreColor.GetHue(), foreColor.GetSaturation(), fBrightness, newr, newg, newb)
foreColor = Color.FromArgb(foreColor.A, Fix(Math.Floor((newr * 255F))), Fix(Math.Floor((newg *
255F))), Fix(Math.Floor((newb * 255F))))
End If
End Sub 'AdjustForeColorBrightnessForBackColor

39.6 What is alpha blending?

Alpha-blending refers to allowing a background color to show through a particular color. You use the static
Color.FromArgb method to create a alpha-blended color. For example,

SolidBrush redBrushSolid = new SolidBrush(Color.FromArgb(255, 255, 0, 0));


SolidBrush redBrushMedium = new SolidBrush(Color.FromArgb(120, 255, 0, 0));
SolidBrush redBrushLight = new SolidBrush(Color.FromArgb(60, 255, 0, 0));

creates three red brushes. The first argument is the alpha-blending value, from 0 to 255. The last three
arguments are the RGB values, denoting in this case, red. In the picture below, all three circles use the color
red, but each circle has a different alpha blending setting, allowing the white background to show through.

39.7 Is there a way to find out the brightness of a Color?

There is a very convenient Color.GetBrightness method that will tell you how close a Color is to black or
white. This is useful when you want to use a bright or a dark color to draw based on whether the
background Color is dark or bright.

39.8 How can a translate an OLE_COLOR into a GDI+ Color object?

Use the ColorTranslator class. It has methods to translate to / from OLE colors, HTML colors, and Win32
colors.

40. GDI+ Books FAQ Home


40.1 GDI+ Programming: Creating Custom Controls using C#?
40.2 Programming Windows with C#?

40.1 GDI+ Programming: Creating Custom Controls using C#?

GDI+ Programming: Creating Custom Controls using C# by Eric White, Chris Garrett.
Wrox Press Inc; ISBN: 1861006314

The title of the this book is kind of misleading. It is an excellent introduction to GDI+. In addition to GDI+
there is also some information on control designers that will be useful to control authors.

40.2 Programming Windows with C#?

Programming Windows(r) with C# (Core Reference) by Charles Petzold

ISBN: 0735613702

This is an excellent book for both Windows Forms and GDI+. As the title suggests it is oriented towards C#
programmers. VB programmers should have no trouble following along. Petzold writes lucid prose.

Update: There is a VB.NET version of this book available now. Programming Microsoft Windows with
Microsoft Visual Basic .NET (Core Reference). ISBN: 0735617996.

41. GDI+ Brushes FAQ Home


41.1 How do I use hatched and gradient brush types?
41.2 How to set the rendering origin for hatch brushes?
41.3 How to create my own hatch styles for brushes?

41.1 How do I use hatched and gradient brush types?

The Brushes Sample shows you how to use four different brushes in several shapes. Below is a code
snippet showing how to use hatched and gradient brushes.

Rectangle rect = new Rectangle(35, 190, 100, 100);


LinearGradientBrush brush2 = new LinearGradientBrush(rect,
Color.DarkOrange, Color.Aquamarine,
LinearGradientMode.ForwardDiagonal);
g.FillEllipse(brush2, 35, 190, 100, 100);

HatchBrush brush1 = new HatchBrush(HatchStyle.DiagonalCross,


Color.DarkOrange, Color.Aquamarine);
g.FillEllipse(brush1, 35, 190, 100, 100);

41.2 How to set the rendering origin for hatch brushes?


The Graphics.RenderingOrigin property lets you specify a Point structure that represents the dither origin
for 8-bits-per-pixel and 16-bits-per-pixel dithering and is also used to set the origin for hatch brushes.

The following example shows how to use RenderingOrigin:

namespace Scrollable1
{
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

///
/// Summary description for ScrollableControl1.
///
public class ScrollableControl1 : System.Windows.Forms.ScrollableControl
{
private void InitializeComponent ()
{
}

public ScrollableControl1()
{
InitializeComponent ();

this.AutoScrollMinSize = new Size(500, 500);


}

protected override void OnPaint(PaintEventArgs pe)


{
pe.Graphics.RenderingOrigin = AutoScrollPosition;
HatchBrush br = new HatchBrush(HatchStyle.ForwardDiagonal, Color.Blue, Color.White);
pe.Graphics.FillRectangle(br, ClientRectangle /*or pe.ClipRectangle*/);
br.Dispose();
}
}
}

41.3 How to create my own hatch styles for brushes?

GDI+ features a TextureBrush that lets you draw repeating patterns. You can specify any bitmap to be
drawn repeatedly. In this example we create bitmaps using code and attach them to a TextureBrush.
static object[] patternSpecs = new object[]
{
new short[] { 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 }, // horizontal
new short[] { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }, // vertical
new short[] { 0x77, 0xbb, 0xdd, 0xee, 0x77, 0xbb, 0xdd, 0xee }, // \\\ Down
new short[] { 0xee, 0xdd, 0xbb, 0x77, 0xee, 0xdd, 0xbb, 0x77 }, // /// Up
new short[] { 0xee, 0x00, 0xee, 0xee, 0xee, 0x00, 0xee, 0xee }, // +++
}

public static Bitmap CreateBitmapFromPattern(int pattern)


{
Bitmap patternBitmap;
IntPtr hBitmap = NativeMethods.CreateBitmap(8, 8, 1, 1, (short[]) patternSpecs[pattern]);
if (hBitmap != IntPtr.Zero)
patternBitmap = Image.FromHbitmap(hBitmap);
NativeMethods.DeleteObject(hBitmap);
return patternBitmap;
}

public static void FillRectangle(Graphics g, Rectangle r, int pattern, Color foreColor, Color
backColor)
{
Bitmap bm = CreateBitmapFromPattern(pattern);
FillRectangle(g, r, bm, foreColor, backColor);
}
public static void FillRectangle(Graphics g, Rectangle r, Bitmap bm, Color foreColor, Color
backColor)
{
if (bm != null)
{
Size size = bm.PhysicalDimension.ToSize();
TextureBrush br = new TextureBrush(bm, new Rectangle(new Point(0, 0), size), ia);
br.WrapMode = WrapMode.Tile;

g.FillRectangle(br, r);
br.Dispose();
}
}

public class NativeMethods


{
[DllImport("gdi32", CharSet=CharSet.Auto, ExactSpelling=true)]
extern public static IntPtr CreateBitmap(int nWidth, int nHeight, int nPlanes, int nBitsPerPixel,
[MarshalAs(UnmanagedType.LPArray)] short[] lpvBits);

[DllImport("gdi32")]
extern public static bool DeleteObject(IntPtr hObject) ;

}
42. GDI+ Drawing Tips FAQ Home
42.1 Where can I see a basic tutorial on GDI+?
42.2 What are some things to remember when drawing in Window Forms?
42.3 When can I not use AutoScrolling? In other words why would I ever need any other form of
autoscrolling?
42.4 Are AutoScrolling bounds setup in World or Device coordinates?
42.5 Why am I not being able to set a Color.Transparent color as a background to my control?
42.6 Why does a Control not draw transparent even after setting it's BackColor to Transparent?
42.7 How can I get the screen resolution of my display?
42.8 How do I draw rotated text?
42.9 Why does my transparent Panel whose parent has a gradient background flicker a lot when resized?
42.10 How do I get a count of the gdi handles currently in use in my application?
42.11 How can I minimize flickering when drawing a control?
42.12 How do I draw circles, rectangles, lines and text?
42.13 How do I get a snapshot of my desktop?
42.14 How can I draw without handling a paint message?

42.1 Where can I see a basic tutorial on GDI+?

Take a look at Mahash Chand's GDI+ Tutorial for Beginners found on C# Corner.

42.2 What are some things to remember when drawing in Window Forms?

Check out the Painting techniques using Windows Forms by Fred Balsigerat gotnetdot.com. It is a good
basic discussion of how to get the best performance from Windows Forms drawing. His hints include
leveraging the power of the .Net Framework by using the proper controls and control styles as well as
consolidating painting code in the OnPaint and OnPaintBackground methods.

42.3 When can I not use AutoScrolling? In other words why would I ever need any other form of
autoscrolling?

AutoScrolling does not allow you to dynamically control the scrolling interval. If you are drawing a
complex control such as grid then you want to be able to scroll based on the current row height, column
width etc. With AutoScrolling you cannot do this. You have to implement Scrolling yourself in such cases.

Autoscrolling is also not very useful if you want multiple views to share a scrollbar. The most common
place where you see this is with a workbook. There is no direct way in Winforms to hook up your own
scrollbars with the AutoScrolling implementation.

42.4 Are AutoScrolling bounds setup in World or Device coordinates?


AutoScrollingMinSize is setup in device coordinates. If you are using a world coordinate system other than
pixels this means that you have to translate between world and device coordinates before you set these
value. You can use the Graphics.TransformPoints API to do this as shown below.

g.TransformPoints(CoordinateSpace.Device, CoordinateSpace.World, ptScrollSize);

All this does is go from the GraphicsUnit that you are using to pixels. For example if your GraphicsUnit is
Inch, then with a Graphics object that represents a monitor screen you will have translated values that come
to about 100 pixels for every logical inch. Using this API ensures that you are insulated from the underlying
device. The values will be much higher for printers. Another important point to remember is that your
Transform in the painting code (please refer earlier FAQ in this section on AutoScrolling implementation)
will have to be in logical coordinates and will hence have to translate between logical and device
coordinates.

protected void OnHandlePaint(object sender, PaintEventArgs args)


{
Graphics g = args.Graphics;
g.PageUnit = GraphicsUnit.Inch;

// this will always be in pixels


Point[] ptAutoScrollPos = new Point[]{this.AutoScrollPosition};

// We have to convert the pixel value (device) to inches (logical..world)


g.TransformPoints(CoordinateSpace.World, CoordinateSpace.Device, ptAutoScrollPos);

// set up a simple translation so that we draw with respect to the doc bounds
// and not the physical bounds
g.TranslateTransform(ptAutoScrollPos[0].X, ptAutoScrollPos[0].Y);

g.DrawEllipse(_pen, _rectEllipse);
}

Play around with the sample and all should be clear. When you run the sample nothing will be seen on the
screen. Scroll around. Remember the logical units are in inches. You will be looking at a huge ellipse!
Source: Syncfusion Staff

42.5 Why am I not being able to set a Color.Transparent color as a background to my control?

Sometimes the framework will throw an exception if you try to set the bg color to be transparent. This is
because the Control doesn't support transparent colors. To work around this you should call this method
from within the Control:

[C#]
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
[VB.Net]
Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)

Depending on the Control, you might also have to perform some custom drawing, then.

42.6 Why does a Control not draw transparent even after setting it's BackColor to Transparent?

This is possible if the Control is drawn by the system, rather than by the framework. This is the case for
example with the Label control when it's set to FlatStyle.System. You should then set to to something else
other than System for your transparent drawing to work.

42.7 How can I get the screen resolution of my display?

Use this property: System.Windows.Forms.Screen.PrimaryScreen.Bounds

42.8 How do I draw rotated text?

private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)


{
Graphics g = e.Graphics;

g.TranslateTransform(100.0f, 100.0f);
g.RotateTransform(-90.0f);
g.DrawString("Vertical Text", Font, Brushes.Blue, 0.0f, 0.0f);
g.ResetTransform();

g.TranslateTransform(100.0f, 100.0f);
g.RotateTransform(-45.0f);
g.DrawString("Slanted Text", new Font(Font, FontStyle.Bold), Brushes.Red, 0.0f, 0.0f);
g.ResetTransform();

42.9 Why does my transparent Panel whose parent has a gradient background flicker a lot when resized?

Make sure to set these flags for your panel, in it's constructor (for example). You will have to derive a class
from Panel otherwise if you were initially using the Panel directly.
base.SetStyle(ControlStyles.DoubleBuffer|ControlStyles.DoubleBuffer|ControlStyles.UserPaint, true);

42.10 How do I get a count of the gdi handles currently in use in my application?

You can do so using the native GetGuiResources api. Here is a sample:

///
/// uiFlags: 0 - Count of GDI objects
/// uiFlags: 1 - Count of USER objects
/// - Win32 GDI objects (pens, brushes, fonts, palettes, regions, device contexts, bitmap headers)
/// - Win32 USER objects:
/// - WIN32 resources (accelerator tables, bitmap resources, dialog box templates, font resources,
menu resources, raw data resources, string table entries, message table entries, cursors/icons)
/// - Other USER objects (windows, menus)
///
[DllImport("User32")]
extern public static int GetGuiResources(IntPtr hProcess, int uiFlags);

public static int GetGuiResourcesGDICount()


{
return GetGuiResources(Process.GetCurrentProcess().Handle, 0);
}

public static int GetGuiResourcesUserCount()


{
return GetGuiResources(Process.GetCurrentProcess().Handle, 1);
}

'
' uiFlags: 0 - Count of GDI objects
' uiFlags: 1 - Count of USER objects
' - Win32 GDI objects (pens, brushes, fonts, palettes, regions, device contexts, bitmap headers)
' - Win32 USER objects:
' - WIN32 resources (accelerator tables, bitmap resources, dialog box templates, font resources,
menu resources, raw data resources, string table entries, message table entries, cursors/icons)
' - Other USER objects (windows, menus)
'
_
extern Public static Integer GetGuiResources(IntPtr hProcess, Integer uiFlags)

Public Shared Function GetGuiResourcesGDICount() As Integer


Return GetGuiResources(Process.GetCurrentProcess().Handle,0)
End Function

Public Shared Function GetGuiResourcesUserCount() As Integer


Return GetGuiResources(Process.GetCurrentProcess().Handle,1)
End Function

42.11 How can I minimize flickering when drawing a control?

The Window.Forms framework offers support for double buffering to avoid flickers through ControlStyles.
Double buffering is a technique that attempts to reduce flicker by doing all the drawing operations on an
off-screen canvas, and then exposing this canvas all at once. To turn on a control's double buffering, you
need to set three styles.

public UserPictureBox() //derived from System.Windows.Forms.Control


{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();

// Activates double buffering


SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);

// TODO: Add any initialization after the InitForm call


}

42.12 How do I draw circles, rectangles, lines and text?

Handle the Paint event for your control or form.

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)


{
Graphics g = e.Graphics;
Pen pen = new Pen(Color.White, 2);
SolidBrush redBrush = new SolidBrush(Color.Red);

g.DrawEllipse(pen, 100,150,100,100);
g.DrawString("Circle", this.Font, redBrush, 80, 150);

g.FillRectangle(redBrush, 140, 35, 20, 40);


g.DrawString("Rectangle", this.Font, redBrush, 80, 50);
g.DrawLine(pen, 114, 110, 150, 110);
g.DrawString("Line", this.Font, redBrush, 80, 104);
}

42.13 How do I get a snapshot of my desktop?

Here is some code that will do it.

[C#]
internal class NativeMethods
{
[DllImport("user32.dll")]
public extern static IntPtr GetDesktopWindow();

[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr hwnd);

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern UInt64 BitBlt
(IntPtr hDestDC,
int x,
int y,
int nWidth,
int nHeight,
IntPtr hSrcDC,
int xSrc,
int ySrc,
System.Int32 dwRop);
}

// Save the screen capture into a jpg


public void SaveScreen()
{
Image myImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height);
Graphics gr1 = Graphics.FromImage(myImage);
IntPtr dc1 = gr1.GetHdc();
IntPtr dc2 = NativeMethods.GetWindowDC(NativeMethods.GetDesktopWindow());
NativeMethods.BitBlt(dc1, 0, 0, Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height, dc2, 0, 0, 13369376);
gr1.ReleaseHdc(dc1);
myImage.Save("screenshot.jpg", ImageFormat.Jpeg);
}
[VB.Net]
Friend Class NativeMethods

_
Public Shared Function GetDesktopWindow() As IntPtr
End Function

_
Public Shared Function GetWindowDC(ByVal hwnd As IntPtr) As IntPtr
End Function

_
Public Shared Function BitBlt(ByVal hDestDC As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal
nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC As IntPtr, ByVal xSrc As Integer, ByVal ySrc
As Integer, ByVal dwRop As System.Int32) As UInt64
End Function
End Class 'NativeMethods

'Save the screen capture into a jpg


Private Sub SaveScreen()
Dim myImage = New Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height)
Dim gr1 As Graphics = Graphics.FromImage(myImage)
Dim dc1 As IntPtr = gr1.GetHdc()
Dim dc2 As IntPtr = NativeMethods.GetWindowDC(NativeMethods.GetDesktopWindow())
NativeMethods.BitBlt(dc1, 0, 0, Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height, dc2, 0, 0, 13369376)
gr1.ReleaseHdc(dc1)
myImage.Save("screenshot.jpg", ImageFormat.Jpeg)
End Sub 'SaveScreen

42.14 How can I draw without handling a paint message?

To draw on any hwnd, you need to get a Graphics object from that hwnd. Once you have the Graphics
object, you can then use its methods to draw. Of course, since this drawing is not done in the Paint handler,
it will not be automatically refreshed when the control is redrawn for any reason.

Graphics g = Graphics.FromHwnd(this.Handle);
SolidBrush brush = new SolidBrush(Color.Red);
Rectangle rectangle = new Rectangle(25, 25, 100, 100);
g.FillRectangle(brush, rectangle);
43. GDI+ Hit Testing FAQ Home
43.1 How to HitTest a polygonal region?

43.1 How to HitTest a polygonal region?

Bool HitTest(PointF[] polygonCorners, PointF mousePosition)


{
GraphicsPath path = new GraphicsPath();
path.AddLines(polygonCorners);
Region region = new Region(path);

// Hittest the region to verify if the point is in the rect


if(region.IsVisible(mousePosition))
return true;
else
return false;
}

44. GDI+ from GDI FAQ Home


44.1 How does text drawing differ between GDI+ and GDI?
44.2 How do I do XOR-type-drawing (SetROP2-Function in MFC) in GDI+?
44.3 Can I mix GDI and GDI+ drawing in my application?
44.4 How do the Win32 System Colors map to the colors provided by System.Drawing.SystemColors?

44.1 How does text drawing differ between GDI+ and GDI?

GDI+ text layout is resolution independent, and forms built with GDI+ text look the same at all resolutions
and when printed. The GDI+ APIs DrawString and MeasureString lay out text independent of device
resolution, so a paragraph of text takes the same number of lines, no matter what the display device.

44.2 How do I do XOR-type-drawing (SetROP2-Function in MFC) in GDI+?

GDI+ doesn't support ROP codes like XOR. To use XOR drawing mode, interop with GDI.

44.3 Can I mix GDI and GDI+ drawing in my application?

You can mix GDI and GDI+ drawing operations in the same code path. The article INFO: Interoperability
Between GDI and GDI+ (Q311221) discusses some caveats to keep in mind when you are writing code that
allows GDI and GDI+ to interoperate. See also the FAQ "How to create my own hatch styles for brushes"
for an example how to use GDI bitmaps with GDI+. The most prominent functions for mixing GDI and
GDI+ are the GetHdc and ReleaseHdc methods of the Graphics class.

44.4 How do the Win32 System Colors map to the colors provided by System.Drawing.SystemColors?

The following table lists all Win32 System Colors and the corresponding name in
System.Drawing.SystemColors type:

GetSysColor(n) SystemColors.
COLOR_ACTIVEBORDER ActiveBorder
COLOR_ACTIVECAPTION ActiveCaption
COLOR_CAPTIONTEXT ActiveCaptionText
COLOR_APPWORKSPACE AppWorkspace
COLOR_3DFACE Control
COLOR_3DSHADOW ControlDark
COLOR_3DDKSHADOW ControlDarkDark
COLOR_3DLIGHT ControlLight
COLOR_3DHIGHLIGHT ControlLightLight
COLOR_BTNTEXT ControlText
COLOR_DESKTOP Desktop
COLOR_GRAYTEXT GrayText
COLOR_HIGHLIGHT Highlight
COLOR_HIGHLIGHTTEXT HighlightText
COLOR_HIGHLIGHT HotTrack
COLOR_INACTIVEBORDER InactiveBorder
COLOR_INACTIVECAPTION InactiveCaption
COLOR_INACTIVECAPTIONTEXT InactiveCaptionText
COLOR_INFOBK Info
COLOR_INFOTEXT InfoText
COLOR_MENU Menu
COLOR_MENUTEXT MenuText
COLOR_SCROLLBAR ScrollBar
COLOR_WINDOW Window
COLOR_WINDOWFRAME WindowFrame
COLOR_WINDOWTEXT WindowText
COLOR_3DHILIGHT ControlLightLight
COLOR_BTNHIGHLIGHT ControlLightLight
COLOR_BTNHILIGHT ControlLightLight
COLOR_BACKGROUND Desktop

45. GDI+ Paths & Regions FAQ Home


45.1 What is a GraphicsPath?
45.2 How can I create non-rectangular windows?
45.3 Is there a imagemap like control in Windows Forms?
45.1 What is a GraphicsPath?

The GraphicsPath class represents a series of connected lines and curves.

Michael Gold uses this class to draw the hands for his Virtual Clock sample found on C# Corner.

45.2 How can I create non-rectangular windows?

Check out this Microsoft KB article, Shaped Windows Forms and Controls in Visual Studio .NET

There are 2 ways to create non-rectangular windows:

1) The Control.Region property (Form inherits this of course):

[CS]
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(0,0,100,100);
gp.AddRectangle(50,50,100,100);
this.Region = new Region(gp);

[VB.NET]
Dim gp As New GraphicsPath()
gp.AddEllipse(0, 0, 100, 100)
gp.AddRectangle(50, 50, 100, 100)
Me.Region = New [Region](gp)

2) Use the Form.TransparencyKey property. This tells the form not to paint any pixels that match the color
of the TransparencyKey. So you can make your fancy skin bitmap, then set the TransparencyKey to be, say
Color.Red, then all the pixels that are RGB(255,0,0) will be transparent.

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

45.3 Is there a imagemap like control in Windows Forms?

There isn't one out of the box. But check out this codeproject article for a control that provides this
functionality.

ImageMap control on Codeproject

46. GDI+ Pens FAQ Home


46.1 Using a wide pen, how do I draw a series of line segments with rounded corners?
46.2 With a wide pen, how can I control how the endpoints of my line appear?
46.1 Using a wide pen, how do I draw a series of line segments with rounded corners?

The LineJoin property of the Pen class allows you to specify how two lines should be joined. The following
code segment produces the picture below.

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)


{
Pen redPen = new Pen(Color.Red, 20);

int startX = 20;


int startY = 60;
int width = this.ClientSize.Width / 17;
int height = this.ClientSize.Height / 2;

foreach(LineJoin LJ in new LineJoin[] { LineJoin.Bevel,


LineJoin.Miter,
LineJoin.Round})
{
redPen.LineJoin = LJ;

Point[] points = {new Point(startX, startY),


new Point(startX + width, startY + height),
new Point(startX + 2 * width, startY),
new Point(startX + 3 * width, startY + height),
new Point(startX + 4 * width, startY)};

e.Graphics.DrawLines(redPen, points);
e.Graphics.DrawString( LJ.ToString(), new Font("Arial Black", 13),
new SolidBrush(Color.Blue), startX - 5, startY - 50);
startX += 4 * width + 40;
}
}

46.2 With a wide pen, how can I control how the endpoints of my line appear?

The LineCap property of the Pen class controls how the ends of your line segments appear. You can set
each end independently using the StartCap and EndCap properties of the Pen class. The following code
segment produces the picture below. $$c private void Form1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e) { Pen redPen = new Pen(Color.LightSalmon, 20); int startX =
80; int startY = 30; int width = this.ClientSize.Width - 2 * startX; Font _font = new Font("Arial Black",
13); foreach(LineCap LC in new LineCap[] { LineCap.ArrowAnchor, LineCap.DiamondAnchor,
LineCap.Flat, LineCap.Round, LineCap.RoundAnchor, LineCap.Square, LineCap.SquareAnchor,
LineCap.Triangle}) { redPen.StartCap = LC; redPen.EndCap = LC; Point p1 = new Point(startX, startY);
Point p2 = new Point(startX + width, startY); e.Graphics.DrawLine(redPen, p1, p2);
e.Graphics.DrawString( LC.ToString(), _font, new SolidBrush(Color.Blue), startX + 40, startY - 13 );

startY += 50; } }$$

48. Interoperability Win32 FAQ Home


48.1 How to add an extern reference to a Win32 API?
48.2 How do I hit a web page from within a button handler in my Windows Forms application?
48.3 How can I capture output from an arbitary console application from within my Window Form
application?
48.4 How do I convert LParam in a message from IntPtr to the Win32 type?
48.5 How do I maximize my main window?
48.6 How can I use 'Hooks' in .NET?
48.7 Is there any way to get to the Edit control or the editHandle of a ComboBox using safe code?
48.8 How do I get the associated Icon from a file in the file system?
48.9 How can I get the directory name for "My Documents" folder and other system directories?
48.10 How can I show a form without making it active?
48.11 How to access a winapi that has a LPTSTR and maxlen param?
48.12 How do I use an exported function (extern "C") from a legacy DLL?
48.13 How can I draw outside my WIndow?
48.14 Is there any way to get detailed error information for Win32 errors when using Platform Invoke?

48.1 How to add an extern reference to a Win32 API?

Use the DllImport attribute that is a member of the System.Runtime.InteropServices namespace.

using System;
using System.Runtime.InteropServices;

class HelloWorld
{
[DllImport("user32.dll")]
public static extern int MessageBoxA(int h, string message, string title, int type);

[DllImport("kernel32.dll")]
public static extern uint GetTickCount();

public static void Main()


{
uint starttime = GetTickCount();
int nReturnValue = MessageBoxA(0,
"Hello World! \nIt is: " + DateTime.Now.ToString(),
"", 0);
Console.WriteLine("\nElapsed time: {0} msecs", GetTickCount() - starttime);

Console.ReadLine();
}
}

48.2 How do I hit a web page from within a button handler in my Windows Forms application?

Use the Process class found in the System.Diagnostics namespace.

Process proc = new Process();


proc.StartInfo.UseShellExecute = true;
proc.StartInfo.FileName = @"http://www.microsoft.com";
proc.Start();

// or just put it all as one statement


//System.Diagnostics.Process.Start(@"http://www.microsoft.com");

48.3 How can I capture output from an arbitary console application from within my Window Form
application?

Use the Process class found in the System.Diagnostic namespace.

Process proc = new Process();

// test.exe is a console application generated by VC6


proc.StartInfo.FileName = @"C:\test\test.exe";

proc.StartInfo.Arguments = "";
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;

proc.Start();
string output = proc.StandardOutput.ReadToEnd();

//output now holds what text.exe would have displayed to the console

48.4 How do I convert LParam in a message from IntPtr to the Win32 type?
Define the struct you want, for example RECT

struct RECT
{
public int left, top, right, bottom;
}

Then use the Message.GetLPAram method

RECT rc = (RECT)m.GetLParam( typeof(RECT) );

48.5 How do I maximize my main window?

To maximize the main window, you can get the handle of the main window in the new process, and then
send a SC_MAXIMIZE system command message to it. You can get the handle through the
Process.MainWindowHandle property. To send a message you should use the DllImportAttribute attribute
to import the API function. This is a sample code:

public class WinAPI


{
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_MAXIMIZE = 0xF030;

[DllImportAttribute ("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
}

Process p = new Process();


p.StartInfo.FileName = @"D:\Program Files\test.exe";
p.Start();
WinAPI.SendMessage(p.MainWindowHandle, WinAPI.WM_SYSCOMMAND,
WinAPI.SC_MAXIMIZE,0);

(from lion_noreply@microsoft.com on microsoft.public.dotnet.framework.windowsforms)

48.6 How can I use 'Hooks' in .NET?

Please check out this article from the October 2000 issue of MSDN Magazine.

Allen Weng gives the following explanation in a post on the


microsoft.public.dotnet.framework.windowsforms newgroup.

If what you are looking for is just to intercept and handle generic Windows messages such as
WM_NCPAINT or alike, you can override WndProc (). You don't need to use the hook procedure. Here is
some code that does this:

public enum WinMsg


{
WM_KEYDOWN = 256,
WM_KEYUP = 257,
WM_PAINT = 15,
WM_CREATE = 1
.......
.......
};

protected override void WndProc(ref System.Windows.Forms.Message m)


{
..............
if (m.Msg == (int) WinMsg.WM_PAINT)
{
m.Result = new IntPtr(0); // no further processing is needed.
.......
.......
}
..............
base.WndProc(ref m);
}

But if you need to use a hook procedure, be cautious since they might interfere with normal execution of
other applications. In some extreme cases, they might bring the whole system down if not processed
correctly. Here is the code snippet that shows you how to do implement and use the hook procedure in
.NET:

public class Win32Hook


{
[DllImport("kernel32")]
public static extern int GetCurrentThreadId();

[DllImport( "user32", CharSet=CharSet.Auto,CallingConvention=CallingConvention.StdCall)]


public static extern int SetWindowsHookEx( HookType idHook,
HOOKPROC lpfn,
int hmod,
int dwThreadId
);

public enum HookType


{
WH_KEYBOARD = 2
}
public delegate int HOOKPROC(int nCode, int wParam, int lParam);

private HOOKPROC hookProc; //private field with class scope


public void SetHook()
{
// set the keyboard hook
hookProc = new HOOKPROC(this.MyKeyboardProc);

SetWindowsHookEx(HookType.WH_KEYBOARD, hookProc, 0,
GetCurrentThreadId());

public int MyKeyboardProc(int nCode, int wParam, int lParam)


{
return 0;
}
}

To install the hook procedure

Win32Hook hook = new Win32Hook();


hook.SetHook();

48.7 Is there any way to get to the Edit control or the editHandle of a ComboBox using safe code?

Bill Zhang (Microsoft) responds to this question in a posting on


microsoft.public.dotnet.frameworks.windowsforms newsgroup.

The Frameworks classes use P/Invoke to call the GetWindow API to get the HWND internally - there is no
exposed way to do this. If you wish to get the Win32 HWND, here's the code to do it, but there is no way to
get a
System.Windows.Forms.Edit control from this.

[DllImport("user32.dll", ExactSpelling=true, CharSet=CharSet.Auto)]


public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);

public const int GW_CHILD = 5;

if (combo.DropDownStyle != ComboBoxStyle.DropDownList) {
IntPtr hwnd = GetWindow(combo.Handle, NativeMethods.GW_CHILD);
if (hwnd != IntPtr.Zero) {
editHandle = hwnd;
}
}
48.8 How do I get the associated Icon from a file in the file system?

Here is a sample prepared by Matthias Heubi that uses interop to access SHGetFileInfo to retrieve icons.

You could also use the ExtractIconEx native api via PInvoke to extract the app icon.

48.9 How can I get the directory name for "My Documents" folder and other system directories?

Mark Boulter (Microsoft) gives code in a posting to the DOTNET newsgroup at


DOTNET@DISCUSS.DEVELOP.COM.

You can also use the System.Environment class to get at this information.

MessageBox.Show( Environment.GetFolderPath(Environment.SpecialFolder.Personal) );

48.10 How can I show a form without making it active?

Normally when you make a Form visible by setting the Visible property to true, it will show the form and
set the focus too. In some cases however, you do not want it to take focus until the user clicks on it. To get
this behavior, do the following utility code:

When you want to show a form without activating it:

UtilFuncs.SetVisibleNoActivate(myForm, true); // true to show.

When you want to hide it:

UtilFuncs.SetVisibleNoActivate(myForm, false); // false to hide.

public class UtilFuncs


{
[DllImport("USER32.dll")]
extern public static bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy,
int uFlags) ;

public const int HWND_TOPMOST = -1; // 0xffff


public const int SWP_NOSIZE = 1; // 0x0001
public const int SWP_NOMOVE = 2; // 0x0002
public const int SWP_NOZORDER = 4; // 0x0004
public const int SWP_NOACTIVATE = 16; // 0x0010
public const int SWP_SHOWWINDOW = 64; // 0x0040
public const int SWP_HIDEWINDOW = 128; // 0x0080
public const int SWP_DRAWFRAME = 32; // 0x0020

public static void ShowWindowTopMost(IntPtr handle)


{
SetWindowPos(handle,
(IntPtr)HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
}

public static void SetVisibleNoActivate(Control control, bool visible)


{
if(visible)
{
ShowWindowTopMost(control.Handle);
control.Visible = true;
}
else
control.Visible = false;
}
}

48.11 How to access a winapi that has a LPTSTR and maxlen param?

[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.Winapi)]

public static extern int GetMenuString(IntPtr hMenu, uint uIDItem,


[MarshalAs(UnmanagedType.LPTStr)]string lpString,int maxCount,uint uFlag);

//Usage:
String caption = new String('t', 30);//using a dummy char ‘t' here.
int len = GetMenuString(hsysmenu, commandID, caption, 30, 0));

48.12 How do I use an exported function (extern "C") from a legacy DLL?

Use the DllImport attribute that is a member of the System.Runtime.InteropServices namespace. Assume
your exported function found in MyDLL.dll has a signature:

int MyFunction( LPCTSTR lpCaption, UINT uType);

The code below shows how you can access this function from within C#.

using System;
using System.Runtime.InteropServices;
class HelloWorld
{
[DllImport("mydll.dll")]
public int MyFunction(string title, int type);

public static void Main()


{
int nReturnValue = MyFunction("some string", 14);
}
}

48.13 How can I draw outside my WIndow?

You have to get a handle to the desktop and draw on the desktop. This means that whatever you draw will
not be automatically refreshed when another window is dragged over it.

[DllImport("User32.dll")]
public extern static System.IntPtr GetDC(System.IntPtr hWnd);

private void button1_Click(object sender, System.EventArgs e)


{
System.IntPtr DesktopHandle = GetDC(System.IntPtr.Zero);
Graphics g = System.Drawing.Graphics.FromHdc(DesktopHandle);
g.FillRectangle(new SolidBrush(Color.Red),0,0,100,100);
}

from a microsoft.public.dotnet.framework.windowsforms posting by Lion Shi (MS)

48.14 Is there any way to get detailed error information for Win32 errors when using Platform Invoke?

Yes, you can use the FormatMessage Win32 API. Sample projects for C# and VB.NET are enclosed. This is
how the declaration looks like:

[DllImport("Kernel32.dll")]
public static extern int FormatMessage(int flags, IntPtr source, int messageId, int languageId,
StringBuilder
buffer, int size, IntPtr arguments );

Called like so:


// You can call FormatMessage to get a descriptive error message
StringBuilder sbFormatMessage = new StringBuilder(1024);
retVal = Interop.FormatMessage(Interop.FORMAT_MESSAGE_FROM_SYSTEM,
IntPtr.Zero, Marshal.GetLastWin32Error(), 0, sbFormatMessage,
sbFormatMessage.Capacity, IntPtr.Zero);

Download C# sample, formatmessage.zip


Download VB.NET sample, formatmessage_VB.zip

49. Interoperability Books FAQ Home


49.1 Are there any books out there that focus on COM interop?

49.1 Are there any books out there that focus on COM interop?

Check out NET and COM: The Complete Interoperability Guide by Adam Nathan Adam Nathan is a
software design engineer on Microsoft's .NET Common Language Runtime QA team. ISBN: 067232170X

50. Interoperability COM FAQ Home


50.1 How do you invoke a COM Class in a specific COM DLL in .Net?
50.2 How do you dynamically invoke a COM class from its GUID?
50.3 How do you make .Net components that could be used by COM?
50.4 How can I read and display Excel files from within my C# application?
50.5 Should I try to use Interoperability or migration to use COM with .NET?
50.6 How can I get events fired by an Office XP chart control hosted in my Windows Forms app?

50.1 How do you invoke a COM Class in a specific COM DLL in .Net?

Imtiaz Alam discusses both early and late binding techniques in his article entitled Accessing COM+
component using C# on C# Corner.

50.2 How do you dynamically invoke a COM class from its GUID?

50.3 How do you make .Net components that could be used by COM?
The tool Regasm.exe can create a COM typelib and creates the necessary entries in the registry (the CLSID
and Typelib ). If only a typelib is required, you can use tlbexp.exe. A com callable wrapper (CCW) will be
created when a COM client (VB, VBS, JS, C++ etc.) creates an instance of a (managed) class. Posted on
C# Corner.

50.4 How can I read and display Excel files from within my C# application?

.NET's interoperability makes it easy to work with COM Capable Applications such as Word and Excel.

See Mike Gold's article on C# Corner for a detailed discussion.

50.5 Should I try to use Interoperability or migration to use COM with .NET?

John Godel tackles this question through a lengthy article on C# Corner. In it, he discusses the basics (and
more) of both .NET Interoperability and Migration.

50.6 How can I get events fired by an Office XP chart control hosted in my Windows Forms app?

To get these events instead of using event delegates, you can create a sink for the events by using the
IConnectionPointContainer and IConnectionPoint interfaces of the Spreadsheet/Chart component. Here are
two articles that you can check:

HOWTO: Handle Office XP Spreadsheet Events in Visual C# .NET


http://support.microsoft.com/support/kb/articles/q319/3/41.asp

HOWTO: Handle Office XP Chart Events in Visual C# .NET


http://support.microsoft.com/support/kb/articles/q319/3/41.asp

Reply posted by Elan Zhou (MS) in microsoft.public.dotnet.framework.windowsforms.

51. Tools Other FAQs FAQ Home


51.1 Are there any easy to use Unit Testing frameworks available for .NET applications?
51.2 Are there any easy to use build tools for .NET applications?
51.3 Are there tools available for generatiing class library documentation for .NET applications?
51.4 How can I generate PDF files from my .NET application?
51.5 CVS integration using C#?
51.6 How can I read and write zip files in my Windows Forms program.
51.1 Are there any easy to use Unit Testing frameworks available for .NET applications?

There are several. Here are a couple of systems that we like. They use .NET debugging support seamlessly
and are thus very painless to use. You have no excuse not to write Unit Tests anymore!

Ladybug Unit Testing software


NUnit

51.2 Are there any easy to use build tools for .NET applications?

Check out NAnt, a free build tool that can be used to automate builds for .NET applications.

51.3 Are there tools available for generatiing class library documentation for .NET applications?

51.4 How can I generate PDF files from my .NET application?

Take a look at the iText# (iTextSharp) library which can be used to generate PDF files.

51.5 CVS integration using C#?

NetCvsLib is a CVS client library written entirely in C# for the .NET platform. Check it out NetCvsLib.

51.6 How can I read and write zip files in my Windows Forms program.

Check out 'The Zip/GZip Implementation For .NET' available here. This library is released under a special
GPL. Check out the above page for details.

52. Tools Resource Editor FAQ Home


52.1 I don't like the resource Editor that comes with Visual Studio.NET. Are there any alternatives out
there?

52.1 I don't like the resource Editor that comes with Visual Studio.NET. Are there any alternatives out
there?

There is one by Lutz Roeder. You can find it here along with other useful tools.

Resourcer for .NET


53. Tools Metadata Viewers FAQ Home
53.1 Are there any tools that allow me to view the rich meta data that .NET assemblies have? Is there a
OLEVIEW equivalent for .NET?
53.2 How do I disassemble a .net assembly (dll/exe) into the IL format?
53.3 How do I create a dll/exe off a previously diassembled .il file?
53.4 How can I launch ILDASM from the VS.NET 2003 IDE?

53.1 Are there any tools that allow me to view the rich meta data that .NET assemblies have? Is there a
OLEVIEW equivalent for .NET?

Currently, the best one that I know of is the Reflector for .NET by Lutz Roeder. You can find it here along
with other useful tools.

Reflector for .NET

You can also use the Windows Class Viewer (wincv.exe) and ILDASM (ildasm), both of which come with
the .NET framework.

53.2 How do I disassemble a .net assembly (dll/exe) into the IL format?

You can covert a dll into it's IL using the ildasm.exe utility. This is usally installed in: C:\Program
Files\Microsoft Visual Studio .NET\FrameworkSDK\Bin

If you want to run this utility via command line it would help if you add the above path to your
Enviornment Path variable.

Here is a sample command line that will disassemble a dll:

ildasm MyFile.exe /output:MyFile.il

You can reassemble the above il after making some minor changes via the ilasm utility. This is usually done
to make some minor changes to an assembly like modifying the version no. of another assembly to which it
links to.

53.3 How do I create a dll/exe off a previously diassembled .il file?

You can create a dll/exe from the il file using the ilasm.exe utility. This utility is usually installed in the
C:\WINNT\Microsoft.NET\Framework\v1.0.3705 (or the appropriate version no.) directory.

If you want to run this utility via command line it would help if you add the above path to your
Enviornment Path variable.
Here is an example command line: // The .res resource file is optional ilasm TextProcessing.il /dll
/output:TextProcessing.dll /resource:TextProcessing.res

53.4 How can I launch ILDASM from the VS.NET 2003 IDE?

Launch VS.NET and choose Tools->External Tools->Add and add settings as show below: Title: ILDASM
(or anything else of your choice)
Command: C:\Program Files\Microsoft.NET\SDK\v1.1\Bin\ildasm.exe
Arguments: $(TargetPath)
Initial Directory: $(TargetDir)
Use Output Window: unchecked
Prompt for arguments: unchecked
Close on exit: checked.

© 2001-06 Copyright George Shepherd.

54. Design Time Serialization FAQ Home


54.1 How to make my Component add itself to the contained Form's IContainer list?
54.2 How do I prevent the default values of my Localized properties form being set?
54.3 How do I force the changes in base class fields to be serialized via a base class property in the
inherited type's designer?

54.1 How to make my Component add itself to the contained Form's IContainer list?

You do this inorder to ensure that your component gets disposed along with the contained Form (logical
parent).

All Form derived classes come with an IContainer field into which many of the .Net components like
ImageList and Timer add themselves to. The Form will dispose the contents of this IContainer from within
its Dispose.

Scenario 1

In order for your Component to get added to this IContainer list, all you have to do is provide a constructor
that takes IContainer as the one and only argument. The design-time will discover this constructor
automatically and use it to initialize your component. You should then add yourself to the IContainer in the
constructor implementation.

Note that for this to work your Component should not have a custom TypeConverter that can convert your
type to an InstanceDescriptor.

Example:

public class MyComponent : Component


{
public MyComponent()
{
}

public MyComponent(IContainer container)


{
container.Add(this);
}
}

Scenario 2

Your components might have more constructors besides the default constructor and you might have a
custom TypeConverter that provides an InstanceDescriptor to let your designer use a non-default
constructor for initializing your component in code.

In this case, the above approach will not work because you do not have an IContainer-argument only
construtor.

You now have to recreate what the design-time did for you. You have to provide a custom
IDesignerSerializationProvider to do so. The attached ContainerInsertingSerializationProvider class can be
used to get the above effect.

54.2 How do I prevent the default values of my Localized properties form being set?

It is normal to have Properties in your Control/Component whose default values are inherited from some
other Control/Component.

In such cases you will normally prevent the designer from storing the property's value in code (using either
DefaultValue attribute or the ShouldSerializeXXX pattern). However, if that property is Localizable and
Localization is turned on, then the property's value will be forced to be stored in the resource. This will
break your property-inheritance logic.

For example:
[
Localizable(true)
...
]
public Font MyControlButtonFont
{
get
{
if(this.buttonFont == null)
return this.Font;
else
return this.buttonFont;
}
set
{
this.buttonFont = value;
}
}

private bool ShouldSerializeMyControlButtonFont()


{
if(this.MyControlButtonFont == this.Font)
return false;
else
return true;
}

In the above case the MyControlDefaultFont inherits its value from the Font property, if its value is not set.
And you use null to determine whether the value is set or not.

But when Localization is ON, the property gets SET and you lose the inheritance logic.

You can avoid this by specifying an AmbientValue attribute for your property, as follows:

[
Localizable(true),
AmbientValue(null)
...
]
public Font MyControlButtonFont

This will use the AmbientValue as the value to persist when there is default-value in your property. This
will prevent your property from getting SET unnecessarily.
54.3 How do I force the changes in base class fields to be serialized via a base class property in the
inherited type's designer?

Sometimes you might want to let the designer serializer serialize the changes in base fields via a property
rather than the field itself using the AccesssedThroughProperty attribute as follows:

public class MyBaseForm : Form


{
[AccessedThroughProperty("MyList")]
private ArrayList myList;

public ArrayList MyList


{
return this.myList;
}
}

Then when the above form is inherited and items get added to the inherited form's designer, code will be
added as follows in the inherited form's InitializeComponent:

private void InitializeComponent()


{
... ... ... ...
this.MyList.Add(aNewItem);
... ... ... ...
}

© 2001-06 Copyright George Shepherd.

55. Design Time Custom Designers FAQ Home


55.1 How do I implement a custom designer?
55.2 I have created a usercontrol and a designer, How can i debug the designer?
55.3 How can I insert custom menu items (verbs) into my Component/Control designer's Context Menu
in design time?
55.4 How do I control the state of my custom verb in my designer?
55.5 How do I restrict my Container Control to parent only certain types of Controls, and vice-versa,
during design-time?
55.6 How do I prevent the Designer-Grid from being drawn on my Container Control during design-
time?
55.7 How do I get Mouse Messages on my Control during design-time?
55.8 Can I do some custom drawing on my control designer's surface during design-time?
55.9 How can I know when a Control/Component has been selected in the designer surface?
55.10 How do I prevent resizing of my Control in the designer?

55.1 How do I implement a custom designer?

Here are a couple of artilces that discuss custom designers.

Shawn Burke, in his article Wrinting Custom Designers for .NET Components at msdn.

Brian Pepin, in his article .NET Shape Library: A Sample Designer at gotnetdot.com.

55.2 I have created a usercontrol and a designer, How can i debug the designer?

You need to use a second instance of VS.NET to debug the one that's running the code.

Put your control on a from in VS.NET Start a 2nd Vs.Net Choose the Debug menu >> Processes ... Double
click "devenv.exe" and choose "Common Language Runtime" as the types of debugging Open your code
file, set your breakpoint, and you're debugging.

Posted by Shawn Burke of MSFT in microsoft.public.dotnet.framework.windowsforms.

55.3 How can I insert custom menu items (verbs) into my Component/Control designer's Context Menu in
design time?

You need to create custom "Verbs" for your Component/Control designer. This will make your "verbs"
show up in the property browser and in the designer context menu.

The designer throws an event when the user selects a verb and you can perform custom operation when you
handle this event.

You do this by overriding the Verbs property in your Designer class.

Here is an example:

public class MyControlExtDesigner : ControlDesigner


{
...
public override DesignerVerbCollection Verbs
{
get
{
if (this.verbs == null)
{
this.verbs = new DesignerVerbCollection();
this.verbs.Add(new DesignerVerb("Add New Child",new EventHandler(this.OnAdd)));
}
return this.verbs;
}
}

private void OnAdd(object sender, EventArgs eevent)


{
// Code to add a new child inside your control.
...
}
}

55.4 How do I control the state of my custom verb in my designer?

You have to store a reference to the DesignerVerb instance you create to represent the custom verb. You can
then update the state of the verb through this reference.

Here is an example:

public class MyControlDesigner :


ParentControlDesigner
{
private DesignerVerb removeVerb;
private DesignerVerbCollection verbs;
...
public override /*ParentControlDesigner*/ void Initialize(IComponent component)
{
...
// Update your designer verb whenever ComponentChanged event occurs.
iComponentChangeService =
IComponentChangeService)this.GetService(typeof(IComponentChangeService));

if (iComponentChangeService != null)
iComponentChangeService.ComponentChanged += new
ComponentChangedEventHandler(this.ComponentChanged);
}
protected override void Dispose(bool disposing)
{
...
if (iComponentChangeService != null)
iComponentChangeService.ComponentChanged -= new
ComponentChangedEventHandler(this.ComponentChanged);

public override DesignerVerbCollection Verbs


{
get
{
if (this.verbs == null)
{
this.removeVerb = new DesignerVerb("Remove Tab",new EventHandler(this.OnRemove));
this.verbs = new DesignerVerbCollection();
this.verbs.Add(this.removeVerb);
}
this.removeVerb.Enabled = (this.Control.Controls.Count > 0);
return this.verbs;
}
}

private void UpdateVerbStatus()


{
if (this.removeVerb != null)
this.removeVerb.Enabled = (this.Control.Controls.Count > 0);
}

private void CheckVerbStatus(object sender, ComponentChangedEventArgs e)


{
this.UpdateVerbStatus();
}
}

55.5 How do I restrict my Container Control to parent only certain types of Controls, and vice-versa, during
design-time?

To restrict your Container Control to parent only certain types of controls, override as follows in your
designer:

public class MyContainerControlDesigner : ParentControlDesigner


{
public override /*ParentControlDesigner*/ bool CanParent(Control control)
{
// My Children can only be of type TextBox.
return (control is TextBox);
}
}

To restrict your Control to get parented to by a certain type, do so in your Control's designer:

class MyControlDesigner : ControlDesigner


{
public override /*ControlDesigner*/ bool CanBeParentedTo(IDesigner parentDesigner)
{
// MyControl can be parent only by MyParent
return (parentDesigner is MyParentDesigner);
// or do this:
// return (parentDesigner.Component is MyParent);
}
}

55.6 How do I prevent the Designer-Grid from being drawn on my Container Control during design-time?

You can do so my overriding the DrawGrid property in your custom designer:

public class MyContainerDesigner : ParentControlDesigner


{
protected override /*ParentControlDesigner*/ bool DrawGrid
{
get
{
if (!this.disableDrawGrid)
return base.DrawGrid;
else
return false;
}
}
}

55.7 How do I get Mouse Messages on my Control during design-time?


The design-time will forward the MouseEnter and MouseLeave messages to your Control by default. The
MouseMove message are blocked by the designer. You can get MouseDown and Up messages in your
Control if you override GetHitTest method in your designer and return true, as follows:

protected override /*ControlDesigner*/ bool GetHitTest(Point point)


{
if(this.NeedMouseDown(point))
return true;
else
return false;
}

55.8 Can I do some custom drawing on my control designer's surface during design-time?

Yes, you can. You have to override OnPaintAdornments in your Control Designer. This will be called after
the Control has painted.

A good example is when you have a Control that has its border style set to None, and you want to draw a
dummy border in the designer.

protected override /*ParentControlDesigner*/ void OnPaintAdornments(PaintEventArgs pe)


{
System.Windows.Forms.Panel panel;
panel = (System.Windows.Forms.Panel)this.Component;
if (panel.BorderStyle == BorderStyle.None)
this.DrawDesignTimeBorder(pe.Graphics, panel);

base.OnPaintAdornments(pe);
}

public void DrawDesignTimeBorder(Graphics g, Control control)


{
System.Drawing.Rectangle clientRectangle;
System.Drawing.Color bgColor, adjustedBgColor;
System.Drawing.Pen pen;

clientRectangle = control.ClientRectangle;
bgColor = control.BackColor;
if (((double) bgColor.GetBrightness()) >= 0.5)
adjustedBgColor = ControlPaint.Dark(control.BackColor);
else
adjustedBgColor = ControlPaint.Light(control.BackColor);

pen = new Pen(adjustedBgColor);


pen.DashStyle = DashStyle.Dash;
clientRectangle.Width = (clientRectangle.Width - 1);
clientRectangle.Height = (clientRectangle.Height - 1);

g.DrawRectangle(pen,clientRectangle);
pen.Dispose();
}

55.9 How can I know when a Control/Component has been selected in the designer surface?

You can listen to the SelectionChanged event in your Control Designer.

public class MyContainerDesigner :


ParentControlDesigner
{
public override /*ParentControlDesigner*/ void Initialize(IComponent component)
{
base.Initialize(component);
iSelectionService = (ISelectionService)this.GetService(typeof(ISelectionService));
if (iSelectionService != null)
iSelectionService.SelectionChanged += new EventHandler(this.OnSelectionChanged);
}
private void OnSelectionChanged(object sender, EventArgs e)
{
// To find out the current selection (can be more than 1) do this:
System.ComponentModel.Design.ISelectionService iSelectionService;
System.Collections.ICollection selectedComponents;

this.iamSelected = false;
iSelectionService = (ISelectionService)this.GetService(typeof(ISelectionService));

if (iSelectionService != null)
{
selectedComponents = iSelectionService.GetSelectedComponents();
foreach(object selectedComponent in selectedComponents)
{
if(selectedComponent == this.Component)
this.iamSelected = true;
}
}
}
}
55.10 How do I prevent resizing of my Control in the designer?

You normally need this support when your Control is parented by another custom Container Control that
manages the location and size of your Control.

You can prevent resizing by overriding this method in your custom ControlDesigner class:

protected override bool EnableDragRect


{
get { return false; }
}

Or, for more control over the resizing process:

public override /*ControlDesigner*/ SelectionRules SelectionRules


{
get
{
System.Windows.Forms.Design.SelectionRules selectionRules;
System.Windows.Forms.Control control;
selectionRules = base.SelectionRules;
control = this.Control;
if (control.Parent is MyControlParent)
selectionRules = (SelectionRules)(selectionRules & ~(SelectionRules.AllSizeable));

return selectionRules;
}
}

© 2001-06 Copyright George Shepherd.

56. Design Time Tips FAQ Home


56.1 When a property gets modified, how do you refresh other properties of a Component/Control in the
property browser?
56.2 How to Reinitialize extender provider dependencies (the logic within CanExtend) from within the
designer?
56.3 How do you detect the designer host getting loaded for the first time in your designer?
56.4 How do you provide "dynamic" default values?
56.5 How to debug your design time code (like designers, typeconverters, etc.)?
56.6 How do you make your custom data types property browser browsable when contained in a
Control/Component (as a property)?
56.7 How to make properties in your custom data type appear in a particular order in the property
browser?
56.8 How do I provide Intellisense support to my controls while coding against them and also provide
Description support for the properties in the property grid?
56.9 How do I change the Zorder of my docked windows at design time?
56.10 How can I tell my form is being used in design time and not runtime?
56.11 How can I persist a collection of items into code?
56.12 How can I supply a list of values to be chosen from a dropdown list at runtime for a specific type
similar to enums?
56.13 How to serialize properties of items that do not implement IComponent in a collection?
56.14 What is the function of TypeDescriptor?
56.15 What is the function of TypeConverters?
56.16 How do I make my custom dialog droppable in the design surface like a component?
56.17 How do I prevent my Component from becoming visible in the VS.Net Toolbox?

56.1 When a property gets modified, how do you refresh other properties of a Component/Control in the
property browser?

Set this attribute for the property:

RefreshProperties(RefreshProperties.Repaint)

56.2 How to Reinitialize extender provider dependencies (the logic within CanExtend) from within the
designer?

Parse through all the Controls in the designer and call TypeDescriptor.Refresh() on them.

// From inside your custom IDesigner implementation:


private void UpdateExtendedProperties()
{
IDesignerHost idh = this.GetService(typeof(IDesignerHost)) as IDesignerHost;
foreach(Component comp in idh.Container.Components)
{
// Ignoring the Form
if((comp is Control) && ((comp is Form) == false))
{
Control ctrl = comp as Control;
TypeDescriptor.Refresh(ctrl);
}
}
}

56.3 How do you detect the designer host getting loaded for the first time in your designer?

Subscribe to IDesignerHost.LoadComplete event. Make any changes to the designerhost (like


adding/deleting component, etc.) only after this event, or else the design document will not be made "dirty".
(IdesignerSerializationManager.SerializationComplete will tell you when Code is deserialized into design
time components).

56.4 How do you provide "dynamic" default values?

Provide ShouldSerialize#PropertyName# and Reset#PropertyName# along with your property.

Example:

private bool ShouldSerializeFont()


{
return this.bFontSet;
}

///
/// Resets the property to its default value.
///
private void ResetFont()
{
this.localFont = null;
}

56.5 How to debug your design time code (like designers, typeconverters, etc.)?

You need to use a second instance of VS.NET to debug the one that's running the code.

Put your control on a from in VS.NET Start a 2nd Vs.Net Choose the Debug menu >> Processes ... Double
click "devenv.exe" and choose "Common Language Runtime" as the types of debugging Open your code
file, set your breakpoint, and you're debugging.
Posted by Shawn Burke of MSFT in microsoft.public.dotnet.framework.windowsforms.

56.6 How do you make your custom data types property browser browsable when contained in a
Control/Component (as a property)?

// Your custom data type


public class MySize
{
...
public int Width{get{...}set{...}}
public int Height{get{...}set{...}}
}

public class MySizeConverter:


ExpandableObjectConverter
{
public override bool GetCreateInstanceSupported(ITypeDescriptorContext context)
{
return true;
}

public override object CreateInstance(ITypeDescriptorContext context, IDictionary propertyValues)


{
MySize size = new MySize();
size.Width = (int)propertyValues[(object)"Width"];
size.Height = (int)propertyValues[(object)"Height"];
return (object)size;
}

56.7 How to make properties in your custom data type appear in a particular order in the property browser?

For example, in the above class (MySize) if you want to your properties "Width" and "Height" to appear in
that order, you should provide this override:

public override bool GetPropertiesSupported(ITypeDescriptorContext context)


{
return true;
}

public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value,


Attribute[] attributes)
{
System.ComponentModel.PropertyDescriptorCollection propertyDescriptorCollection;
string[] propNames;
propertyDescriptorCollection =
TypeDescriptor.GetProperties(typeof(System.Drawing.Size),attributes);
propNames = (string[])new System.String[2];
propNames[0] = @"Width";
propNames[1] = @"Height";
return propertyDescriptorCollection0.Sort(propNames);
} // end of method GetProperties

56.8 How do I provide Intellisense support to my controls while coding against them and also provide
Description support for the properties in the property grid?

You can provide Intellisense support to your type and it's members by providing xml comments in code as
follows:

///
/// Summary description for Form3.
///
public class Form3 : System.Windows.Forms.Form
{
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
}
///
/// Summary of my property
///
public bool MyProperty
{
get{..}
set{..}
}
}

Search for the "Tags for Documentation Comments" topic in MSDN for all the avilable documentation
tags.

Then in your project, go to the Project Properties dialog, to the Configuration Properties/Build tab and
specify a file for the XML Documentation File property. This will generate a file by that name when you
compile your assembly. Place this xml file beside your dll. This will provide Intellisense support for your
types in that assembly.

To provide Description support for your properties in the property grid in the designer, add the
DescriptionAttribute attribute to your propeties in code.
56.9 How do I change the Zorder of my docked windows at design time?

You can use the menu selection Format|Move To Front or Format|Send To Back to change the Zorder and
update your docking.

56.10 How can I tell my form is being used in design time and not runtime?

Check the the property Form.DesignMode.

But, note that when in Visual Inheritance mode (designing a derived form), your Control's DesignMode
property will be true when the base form's constructor gets executed in the design-time.

To workaround this, you could check if the app in which your control is running is not devenv.exe, as
follows:

string exePath = Application.ExecutablePath;


exePath = exePath.ToLower();
if(Application.ExecutablePath.ToLower().IndexOf("devenv.exe") > -1)
{
// Then you are running in vs.net.
}

56.11 How can I persist a collection of items into code?

The CollectionEditor allows adding and removing items from a collection at design time. If the items in
this collection implement IComponent or if they are derived from Component, the items in your collection
can be persisted in code.

Download collectioneditorsample.zip for a complete sample project.

Here are some steps you should follow:


1) Make sure your item is derived from Component or implemnts Icomponent.
For example:

public class SomeItem : Component


{
private string label = "";

public SomeItem()
{
}

public SomeItem(string label)


{
this.label = label;
}

public string Label


{
get
{
return label;
}
set
{
label = value;
}
}

public override string ToString()


{
return String.Format("SomeItem: ( Label = '{0}' )", label);
}
}

2) Next implement your Collection. You have to implement the Ilist interface. The CollectionEditor will
determine the type of instances to be added to your collection using reflection inspecting the return type of
the Item property (Indexer).

[
Description("The set of properties to be edited with CollectionEditor."),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Editor(typeof(System.ComponentModel.Design.CollectionEditor),
typeof(System.Drawing.Design.UITypeEditor))
]
public SomeItemCollection SomeItems
{
get
{
if (someItemCollection == null)
{
someItemCollection = CreateItemCollection();
}
return someItemCollection;
}
}

protected SomeItemCollection CreateItemCollection()


{
return new SomeItemCollection(this);
}
public class SomeItemCollection : IList
{
// Fields
private SomeItemDisplayer owner;
public event EventHandler Changed;

// Constructors
public SomeItemCollection(SomeItemDisplayer owner)
{
this.owner = owner;
}

internal ArrayList InnerArray


{
get
{
return owner.someItems;
}
}

public void OnChanged()


{
if (this.Changed != null)
this.Changed(this, EventArgs.Empty);
}

///
/// The CollectionEditor will determine the type of objects to be created by
/// looking at the property type of the following method. CollectionEditor
/// internally uses reflection to get the PropertyInfo for the "Item" property.
/// This method must be public.
///
public SomeItem this[int index]
{
set
{
if (value == null)
throw new ArgumentNullException("value");

if (index < 0 || index >= this.InnerArray.Count)


throw new ArgumentOutOfRangeException(String.Format("Invalid Argument {0}:
{1}", "index", index.ToString()));

this.InnerArray[index] = value;
OnChanged();
}
get
{
if (index < 0 || index >= this.InnerArray.Count)
throw new ArgumentOutOfRangeException("Invalid Argument {0}: {1}", "index",
index.ToString());
return (SomeItem) this.InnerArray[index];
}
}

public void AddRange(object[] items)


{
InnerArray.AddRange(items);
OnChanged();
}

///
/// This implementation for the Item property for the IList interface. It's
/// property type is object.
///
object IList.this[int index]
{
set
{
// forward call to public indexer
this[index] = (SomeItem) value;
}
get
{
// forward call to public indexer
return this[index];
}
}

public /*IEnumerable*/ IEnumerator GetEnumerator()


{
return InnerArray.GetEnumerator();
}

public /*ICollection*/ int Count


{
get
{
return InnerArray.Count;
}
}

public /*IList*/ void RemoveAt(int index)


{
if (index < 0 || index >= this.InnerArray.Count)
throw new ArgumentOutOfRangeException(String.Format("Invalid Argument {0}: {1}",
"index", index.ToString()));

this.InnerArray.RemoveAt(index);
OnChanged();
}

public /*IList*/ void Remove(object value)


{
int n = this.InnerArray.IndexOf(value,0);
if (n != -1)
this.RemoveAt(n);
}

public /*IList*/ void Insert(int index, object item)


{
if (item == null)
throw new ArgumentNullException("item");
if (index < 0 || index > this.InnerArray.Count)
throw new ArgumentOutOfRangeException(String.Format("Invalid Argument {0}:
{1}","index", index.ToString()));

this.InnerArray.Insert(index,item);
OnChanged();
}

public /*IList*/ int IndexOf(object value)


{
if (value == null)
throw new ArgumentNullException(String.Format("Invalid Argument {0}: {1}","value",
"null"));
return this.InnerArray.IndexOf(value,0);
}

public /*IList*/ bool IsReadOnly


{
get
{
return false;
}
}

public /*IList*/ void Clear()


{
InnerArray.Clear();
this.owner.Invalidate();
}

public /*IList*/ bool Contains(object value)


{
return this.IndexOf(value) != -1;
}

void System.Collections.ICollection.CopyTo(Array dest, int index)


{
int count = this.InnerArray.Count;
for (int n1 = 0; n1 < count; n1++)
dest.SetValue(this.InnerArray[n1], (n1 + index));
}

int System.Collections.IList.Add(object item)


{
int n = this.InnerArray.Add(item);
OnChanged();
return n;
}

bool System.Collections.IList.IsFixedSize
{
get
{
return false;
}
}

bool System.Collections.ICollection.IsSynchronized
{
get
{
return false;
}
}

object System.Collections.ICollection.SyncRoot
{
get
{
return this;
}
}

3) Reference this collection in your control or component that should be designable. You need to supply a
DesignerSerializationVisibility and an Editor attribute:
private SomeItemCollection someItemCollection = null;
ArrayList someItems = new ArrayList();

[
Description("The set of properties to be edited with CollectionEditor."),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
Editor(typeof(System.ComponentModel.Design.CollectionEditor),
typeof(System.Drawing.Design.UITypeEditor))
]
public SomeItemCollection SomeItems
{
get
{
if (someItemCollection == null)
{
someItemCollection = CreateItemCollection();
}
return someItemCollection;
}
}

protected SomeItemCollection CreateItemCollection()


{
return new SomeItemCollection(this);
}

56.12 How can I supply a list of values to be chosen from a dropdown list at runtime for a specific type
similar to enums?

You have to implement a TypeConverter for your class and override the GetStandardValues and
GetStandardValuesSupported method. In your override of GetStandardValuesSupported you have to
return true. In your override of GetStandardValues you should return the list of values.

Optionally you can override GetStandardValuesExclusive and allow the user to specify values that are not
in the value list.

Note: The standard values collection can be initialized at runtime depending on the context of the instance
object.

public class GridCellValueTypeConverter: TypeConverter


{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(System.String))
return true;
return base.CanConvertFrom(context,sourceType);
}

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object


value)
{
if (value is System.String)
{
if (((string) value) != "")
return Type.GetType((string) value);
else
return null;
}

return base.ConvertFrom(context,culture,value);
}

// no string conversion
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value,
Type destinationType)
{
if (destinationType == typeof(String))
{
Type type = (Type) value;
if (type == null)
return String.Empty;
else if (type.Namespace == "System")
return type.ToString();
else
{
return String.Concat(type.FullName, ",", type.AssemblyQualifiedName.Split(',')[1]);
}
}

return base.ConvertFrom(context,culture,value);

public override System.ComponentModel.TypeConverter.StandardValuesCollection


GetStandardValues(ITypeDescriptorContext context)
{
return svc;
}

public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)


{
return false;
}

public override bool GetStandardValuesSupported(ITypeDescriptorContext context)


{
return true;
}

// Fields
static GridCellValueTypeConverter()
{
values = new string[]
{
"System.String",
"System.Double",
"System.Int32",
"System.Boolean",
"System.DateTime",
"System.Int16",
"System.Int64",
"System.Single",
"System.Byte",
"System.Char",
"System.Decimal",
"System.UInt16",
"System.UInt32",
"System.UInt64",
};
Array.Sort(values);
Type[] types = new Type[values.Length];
for (int i = 0; i < values.Length; i++)
types[i] = Type.GetType(values[i]);
svc = new TypeConverter.StandardValuesCollection(types);
}

private static string[] values;


private static TypeConverter.StandardValuesCollection svc;
}

56.13 How to serialize properties of items that do not implement IComponent in a collection?

You have to set DesignerSerializationVisibility attribute on the property whose type is a strongly-typed
collection to Content. You have to ensure the collection is created at statup or on demand.

In order to support serialization of items that do not implement IComponent into your code you have to
write a TypeConverter for that class that can convert to InstanceDescriptor.

See the documentation on InstanceDescriptor for an example.

56.14 What is the function of TypeDescriptor?


Create a "Window" menu in you mdi parent form's main-menu and then drop another MenuItem into it,
setting it's MdiList propety to true. It will then expand to show all the available mdi children during
runtime.

56.15 What is the function of TypeConverters?

Type converters let you convert one type to another type. Each type that you declare can optionally have a
TypeConverter associated with it using the TypeConverterAttribute. If you do not specify one the class will
inherit a TypeConverter from its base class.

The following methods deal with the type conversion work that is performed by TypeConverters.

// for conversion from another type to the type that this type converter is associated with
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType);
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value);

// for conversion of this type to some other type


public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType);
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type
destinationType);

The above functions provide the core of TypeConverters. One reason for the confusion surrounding
TypeConverters is the fact that they have other functions that are unrelated to the primary type conversion
function. Methods such as public PropertyDescriptorCollection GetProperties(ITypeDescriptorContext
context, object value) do not perform type conversion. They are present for another purpose.

Typically when we require access to the properties, events and methods we use a TypeDescriptor. However
there are .NET framework elements such as the PropertyGrid that first access the TypeConverter and then
query it for a list of Properties (it it returns true when public bool GetPropertiesSupported(); is called). If
the TypeConverter returns false from public bool GetPropertiesSupported(), then the TypeDescriptor is
queried for such information. Deriving a type converter is an easy way to present properties, events etc in
any manner that you want especially with the property grid. In your own code also when you access
Property information it is good practice to query the TypeConverter first. So, presentation of object
properties, methods and events is also a function of the TypeConverter. Unfortunately, the name
'TypeConverter' does not hint at this function.

Enclosed is a small sample that illustrates the use of a custom Type Converter for conversion. Download
TypeConverter.zip. Try the sample and it will be clear what Type Converters primarily do.

For more information on TypeDescriptors please refer to


http://www.syncfusion.com/faq/winforms/search/705.asp

56.16 How do I make my custom dialog droppable in the design surface like a component?
Set the Designer attribute for your custom dialog to be ComponentDesigner (instead of the default
ControlDesigner). That should make it droppable in the design surface as a component.

56.17 How do I prevent my Component from becoming visible in the VS.Net Toolbox?

Use the ToolboxItem(false) attribute on your Component/Control class. This will prevent it from appearing
in the Toolbox.

[ToolboxItem(false)]
public class MyComponent : Component{..}

© 2001-06 Copyright George Shepherd.

57. Design Time Type Editors FAQ Home


57.1 In my UITypeEditor for a collection, how do I change the "(collection)" string to a string of my
own?
57.2 How can I allow my user to add more than 1 type of object to my collection, during design-time?
57.3 How can I let the user edit my Multi-Dimensional collection?
57.4 What should I do to make my StringCollection property editable during design-time?
57.5 From within a PropertyGrid, is there any way to display property names that differ from the actual
class property names?
57.6 How do I make a class expandable within the property browser?
57.7 How can I paint a represenation of enum values using a UITypeEditor?

57.1 In my UITypeEditor for a collection, how do I change the "(collection)" string to a string of my own?

The string "(Collection)" is coming from the TypeConverter on that property, which is CollectionConverter.
To modify this value, do the following...
[TypeConverter(typeof(MyCollectionConverter)]
public class MyCollection : SomeBaseCollectoin
{
// ...
}

internal class MyCollectoinConverter : System.ComponentModel.CollectionConverter


{
public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
if (value is ICollection)
{
return "You can return what ever string value you want
here";
}
}
return base.ConvertTo(context, culture, value, destinationType);
}
}

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

57.2 How can I allow my user to add more than 1 type of object to my collection, during design-time?

The default CollectionEditor will allow your user to add objects of type returned by your collection's
indexer method.

You can make this CollectionEditor allow your user to pick the type of object to add by deriving from
CollectionEditor and making the change as shown below. This will introduce a drop-down in the editor's
"Add" button to allow the user to pick the type he wants to add.

public class CustomCollectionEditor : System.ComponentModel.Design.CollectionEditor


{
private Type[] types;
public CustomCollectionEditor(Type type)
: base(type)
{
types = new Type[]{typeof(ItemType1), typeof(ItemType2), typeof(ItemType3),
typeof(ItemType4)};
}

// Return the types that you want to allow the user to add into your collection.
protected override Type[] CreateNewItemTypes()
{
return types;
}
}

[Editor(typeof(CustomCollectionEditor), typeof(UITypeEditor))]
public class CustomCollection : IList
{
...
}

57.3 How can I let the user edit my Multi-Dimensional collection?

This is usually a problem if you have a custom collection type MyCollection which itself can take items of
type MyCollection.

The problem is because a single instance of a UITypeEditor is used by the framework irrespective of how
many types and instances it serves to edit. Which means you cannot start editing your MyCollection from
within a MyCollection editor, since the editor is already open.

To work around this problem, you can provide a custom editor as follows:

public class CustomCollectionEditor : CollectionEditor


{
// The base class has its own version of this property
// cached CollectionForm
private CollectionForm collectionForm;

public CustomCollectionEditor(Type type)


: base(type)
{
}

public override object EditValue(


ITypeDescriptorContext context, IServiceProvider provider,
object value)
{
if(this.collectionForm != null && this.collectionForm.Visible)
{
// If the CollectionForm is already visible, then create a new instance
// of the editor and delegate this call to it.
BarItemsCollectionEditor editor = new BarItemsCollectionEditor(this.CollectionType);
return editor.EditValue(context, provider, value);
}
else return base.EditValue(context, provider, value);
}
protected override CollectionForm CreateCollectionForm()
{
// Cache the CollectionForm being used.
this.collectionForm = base.CreateCollectionForm();
return this.collectionForm;
}
}

57.4 What should I do to make my StringCollection property editable during design-time?

Use this custom editor attribute for the property that is of the StringCollection type (this can be used for
other Collection types too if you want to allow entry of strings into the collection during design-time).

Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design",
"System.Drawing.Design.UITypeEditor, System.Drawing"),
public YourCollection YourProp{get{...}set{...}}

StringCollectionEditor is not public so you have to use the above constructor override and specify the
typename. This editor should allow you to edit your collection without any problems.

57.5 From within a PropertyGrid, is there any way to display property names that differ from the actual
class property names?

You can do this but it's not as simple as using an attribute. If you want to modify the property names for
your component, you have to interact with the reflection mechanism that the grid is using by implementing
ICustomTypeDescriptor. The grid operates on objects called PropertyDescriptors with are the Framework's
generic wrapper for a property, where reflection is a specific implementation. So what
ICustomTypeDescriptor allows you to do is to have *your object* asked for it's properties rather than than
the default system, which is reflection.

You then write your own derived version of PropertyDescriptor (an abstract class in
System.ComponentModel) and return your property descriptors instead of the ones that come back from the
TypeDescriptor... so some of the impl would look something like this.

public class MyFriendlyNamePropertyDescriptor : PropertyDescriptor


{
private PropertyDescriptor baseProp;
private string friendlyName;
public MyFriendlyNamePropertyDescriptor(PropertyDescriptor baseProp, Attribute[] filter)
: base(baseProp)
{
this.baseProp = baseProp;
}

public override string Name


{
get{return this.baseProp.Name;}
}

public override string DisplayName


{
get
{
return GetFriendlyname(baseProp.Name); //replace with code to return a friendly name
}
}

public override bool IsReadOnly


{
get {return baseProp.IsReadOnly;}
}

public override bool CanResetValue(object component)


{
return this.baseProp.CanResetValue(component);
}

public override Type ComponentType


{
get{return baseProp.ComponentType;}
}

public override object GetValue(object component)


{
return this.baseProp.GetValue(component);
}

public override Type PropertyType


{
get{return this.baseProp.PropertyType;}
}
public override void ResetValue(object component)
{
baseProp.ResetValue(component);
}
public override void SetValue(object component, object Value)
{
this.baseProp.SetValue(component, Value);
}
public override bool ShouldSerializeValue(object component)
{
return this.baseProp.ShouldSerializeValue(component);
}

public class MyClass : ICustomTypeDescriptor


{

PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] filter)


{
PropertyDescriptorCollection baseProps = TypeDescriptor.GetProperties(GetType(), filter);
// notice we use the type here so we don't recurse
PropertyDescriptor[] newProps = new PropertyDescriptor[baseProps.Count];
for (int i = 0; i < baseProps.Count; i++)
{
newProps[i] = new MyFriendlyNamePropertyDescriptor(baseProps[i], filter);
string oldname = ((PropertyDescriptor)baseProps[i]).DisplayName ;
string newname = ((MyFriendlyNamePropertyDescriptor)newProps[i]).DisplayName;
}
// probably wanna cache this...
return new PropertyDescriptorCollection(newProps);
}

AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
return TypeDescriptor.GetAttributes(this, true);
}

string ICustomTypeDescriptor.GetClassName()
{
return TypeDescriptor.GetClassName(this, true);
}

string ICustomTypeDescriptor.GetComponentName()
{
return TypeDescriptor.GetComponentName(this, true);
}

TypeConverter ICustomTypeDescriptor.GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}

EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}

EventDescriptorCollection ICustomTypeDescriptor.GetEvents(System.Attribute[] attributes)


{
return TypeDescriptor.GetEvents(this, attributes, true);
}
EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
{
return TypeDescriptor.GetEvents(this, true);
}
PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(this, true);
}

PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
return TypeDescriptor.GetProperties(this, true);
}

object ICustomTypeDescriptor.GetEditor(System.Type editorBaseType)


{
return TypeDescriptor.GetEditor(this, editorBaseType, true);
}
object ICustomTypeDescriptor.GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd)
{
return this;
}

// the code for MyClass.... including the properties to show in the propertygrid

(originally from sburke_online@microsoft..nospam..com on


microsoft.public.dotnet.framework.windowsforms. This code suggested by Rachid El Masoudi in an email
to winformsfaq@syncfusion.com)

57.6 How do I make a class expandable within the property browser?

Add a TypeConverter to your class type to tell the Property Browser it should be expandable.

[TypeConverter(typeof(ExpandableObjectConverter))]
public class MyClass
{
}

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

57.7 How can I paint a represenation of enum values using a UITypeEditor?


The following HatchStyleEditor class draws a graphical representation for values in the HatchStyle
enumeration. HatchStyleEditor is derived from UITypeEditor and ovverides the GetPaintValueSupported
method and returns true. GetPaintValueSupported indicates that this editor supports the painting of a
representation of an object's value. PaintValue paints the representative value to the canvas.

public class HatchStyleEditor : UITypeEditor


{
public override bool GetPaintValueSupported(ITypeDescriptorContext context)
{
return true;
}

public override void PaintValue(PaintValueEventArgs e)


{
if (e.Value is HatchStyle)
{
HatchStyle hatch = (HatchStyle) e.Value;
Brush br = new HatchBrush(hatch, SystemColors.WindowText, SystemColors.Window);
e.Graphics.FillRectangle(br, e.Bounds);
br.Dispose();
}
}
}

58. Design Time UI FAQ Home


58.1 How do you prevent certain Controls from appearing in the property browser during designtime?
58.2 At designtime, how can I hide a base class property in my derived control from the user?
58.3 How do I add a custom tab to the property grid when it is displaying my object's properties?
58.4 How do I prevent my Control's properties from getting combined with properties belonging to other
objects in a Properties window?
58.5 How do I make some properties not browsable in the designer, but browsable in the editor?

58.1 How do you prevent certain Controls from appearing in the property browser during designtime?

Set the DesignTimeVisible(false) attribute. You can still provide a TypeConverter to make it participate in
designer Serialization.

58.2 At designtime, how can I hide a base class property in my derived control from the user?
Set the Browseable attribute on the new property that hides the existing one. Here is a code snippet that
hides the WordWrap property in the derived TextBox.

[C#]
public class MyTextBox : TextBox
{
[Browsable(false)]
public new bool WordWrap
{
get{ return false;} //always false
set{}
}
}

[VB.NET]
Public Class MyTextBox
Inherits TextBox

_
Public Shadows Property WordWrap() As Boolean
Get
Return False 'always false
End Get
Set 'empty
End Set
End Property
End Class 'MyTextBox

58.3 How do I add a custom tab to the property grid when it is displaying my object's properties?

We have a small sample that shows how to do this. Download PropTab.zip. After you download and unzip
the sample, build the project. Both the control assembly and a small driver assembly get built. After that
add the control to your toolbox using 'Customise toolbox...'. Then drag and drop an instance of the added
control onto the form in the driver winforms sub-project. When you select this control the properties
window should have a tab with a bitmap 'T' as shown below.

These are the steps involved. Before following these steps please download and take a look at the sample.
That will greatly help when following these steps.

Control related steps

Assume that you have a control that has two sets of properties, one set that you wish to have displayed in
the main property tab and another set that you wish to have displayed in the second tab.
• Mark those properties that you wish to display in the first tab with the BrowsableAttribute to true.
• Mark those properties that you wish to display in the second tab with the BrowsableAttribute set to
false. Create another attribute. Name it anything you want and give it a single boolean property.
Initialize this property to true.

Other steps

• Derive a class from System.Windows.Forms.PropertyGridInternal.PropertiesTab. You have to


override a few methods. The most important of these is GetProperties. We override GetProperties as
shown below to use our CustomAttribute as the filtering attribute instead of the BrowsableAttribute
that the PropertyGrid uses by default.

public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object


component, Attribute[] attrs)
{
return TypeDescriptor.GetProperties(component, new Attribute[]
{new BrowsableAttribute(false), new CustomTabDisplayAttribute(true)});
}

Create a embedded resource bitmap with the same name as the derived tab's type. This bitmap had to
be 16x16.

A brief note of explanation on the sample. The sample shows a user control that displays its own tab for
some properties. These properties are marked with the filtering attribute, CustomTabDisplayAttribute. The
rest of the properties are just displayed in the normal property tab and need no special attention.

To get a deeper understanding of how this works, please refer to these FAQs on TypeConverters and
TypeDescriptors.

• TypeDescriptors
• TypeConverters

58.4 How do I prevent my Control's properties from getting combined with properties belonging to other
objects in a Properties window?

Use the Mergable(false) attribute. This will prevent your Property from being edited as part of a group in
the designer.

58.5 How do I make some properties not browsable in the designer, but browsable in the editor?

Provide the follwoing attributes to your Property:

[Browsable(false), EditorBrowsable(EditorBrowsableState.Always)]
public bool YourProperty{get{}set{}}

59. VS.NET Tips FAQ Home


59.1 Is there any easy way to convert C# code to VB.NET?
59.2 Is there any easy way to convert VB.NET code to C#?
59.3 How can I word-wrap the Tooltip that is dispayed?
59.4 How do I add a tooltip to my Button control?
59.5 How can I have a multiline tooltip?
59.6 How do I use VS to add an override for a virtual member of a baseclass?
59.7 How do I compile unsafe code in VS.NET?
59.8 How to convert an application project to class library project, and vice versa?
59.9 How do I start Visual Studio.NET from the command line?
59.10 What are the options with using Visual Studio.NET from the command line?
59.11 How do I create and use a component?
59.12 In Visual Studio, all my docking windows are out of whack. How can I reset them so things will be
docked properly?
59.13 How do I move a docked control around (or change the dock order) in my Form?
59.14 How can I instruct the compiler to use the Main method in Class2 instead of Class1?
59.15 Whenever I share files between projects it appears that Visual Studio.NET copies the files over
into the new project. I want to just share the file and not have it copied over. Is there any way to do this?
59.16 How can I graphically set the tab order for controls on a form?
59.17 How can I speed up my work in Visual Studio?
59.18 I have code snippets that I use often. How can I manage them so I can easily used them?
59.19 Can I drag and drop code snippets using the VS.NET IDE?
59.20 In VS.NET, how can I change the build order of projects in my solution?
59.21 In VS.NET, how can I specify the start up project for my application?
59.22 If I create an assembly, how can I see the assembly/components from with the VS.Net "Add..."
dialogs?
59.23 How does VS.Net find the referenced assemblies when I build a project from the command line?
59.24 How can I get the default namespace of a C# project in VS.NET?
59.25 How can I open a project created with Visual Studio .NET 2003 in Visual Studio .NET 2002?
59.26 How can I change the Word Wrap Property of VS.NET IDE?

59.1 Is there any easy way to convert C# code to VB.NET?

Yes, there is. Check this out: http://csharpconverter.claritycon.com/Default.aspx or


http://www.kamalpatel.net/ConvertCSharp2VB.aspx

59.2 Is there any easy way to convert VB.NET code to C#?

SharpDevelop includes a VB.NET to C# converter. GBVB ,Convertvbtocsharp , BabbelFisken are other


options and there are also converters that are commercially available.
59.3 How can I word-wrap the Tooltip that is dispayed?

Rhett Gong posted a work around using Reflection to achieve this in the
microsoft.public.dotnet.framework.windowsforms.controls Newsgroup:

[DllImport("user32.dll")]
private extern static int SendMessage(IntPtr hwnd,uint msg, int wParam, int lParam);

.....
object o = typeof(ToolTip).InvokeMember("Handle",BindingFlags.NonPublic|BindingFlags.Instance|
BindingFlags.GetProperty,null,myToolTip,null);
IntPtr hwnd = (IntPtr) o;
SendMessage(hwnd,0x0418, 0, 300);
.....

59.4 How do I add a tooltip to my Button control?

From within the designer:


1) From the ToolBox, drap a ToolTip control to your form.
2) Check the properties of this toolTip1 object to make sure Active is set to true.
3) Click on your button, and in its Property page, set the ToolTip on toolTip1 entry.

From code:

private System.Windows.Forms.ToolTip toolTip1;


......
......
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.toolTip1.Active = true;
......
......
this.toolTip1.SetToolTip(this.button1, "Press for information...");

59.5 How can I have a multiline tooltip?

Include a \n as part of the tiptext.

this.toolTip1.SetToolTip(this.button1, "Press for\ninformation...");


59.6 How do I use VS to add an override for a virtual member of a baseclass?

In the ClassView window, expand the base class under your derived class. Then right-click the desired
method, and select Add.

59.7 How do I compile unsafe code in VS.NET?

Click "Project | Properties" from the menus.


Select "Configuration Properties" folder and the "Build" item under that.
Switch "Allow unsafe code blocks" from "False" to "True".

(from Ryan LaNeve on microsoft.public.dotnet.framework.windowsforms)

59.8 How to convert an application project to class library project, and vice versa?

In the Solutions Explorer window, right-click the exe project and then select Properties in the popup. Then
change the Output type from Windows Application to Class Library. You may also want to comment out the
Main method in your code as it is not needed in the library project.

To convert from a DLL to and exe, reverse the process.

59.9 How do I start Visual Studio.NET from the command line?

Simply type devenv.exe from the command line. If you get a message like this, then you do not have
devenv.exe in your path. >>> 'devenv.exe' is not recognized as an internal or external command, operable
program or batch file. >>> To fix this simply run the batch file, vsvars32.bat that comes with Visual
Studio.NET from the command line in the working folder. After you run this batch file devenv.exe will be
available from the command line in that folder.

59.10 What are the options with using Visual Studio.NET from the command line?

Type devenv.exe /? to get a full list of options.

59.11 How do I create and use a component?

Take a look at Mahash Chand's Creating C# Class Library (Dll) found on C# Corner.

59.12 In Visual Studio, all my docking windows are out of whack. How can I reset them so things will be
docked properly?
You can use the menu item Tools|Options, an dthen seelct Reset Window Layout.

A second alternative is to close Visual Studio, and then delete the suo file in your project folder.
(suo=Studio User Options)

59.13 How do I move a docked control around (or change the dock order) in my Form?

You cannot move it via drag-and-drop. But you change it's position or dock order by selecting the "Bring
To Front" or "Send To Back" verbs in it's context menu. "Bring To Front" will move it to the top of the
children list and "Send To Back" will move it to the last of the children list. This is possible because the
docking logic will be applied on the children in the order in which they appear in the child controls list.

59.14 How can I instruct the compiler to use the Main method in Class2 instead of Class1?

In the project's General Properities, specify Class2 as the "Startup Object". The dropdown contains all
classes with a Main method specified.

59.15 Whenever I share files between projects it appears that Visual Studio.NET copies the files over into
the new project. I want to just share the file and not have it copied over. Is there any way to do this?

When you add an existing item from with the Visual Studio.NET IDE, click the small arrow on the 'Open'
button in the dialog that is presented. You will see a list of options. One of these is to 'Link file'. If you
select this option then you will not get a local copy and any changes that you make to the linked file will be
in the original file. Another way to get the same effect is to share the files using Visual Source Safe. You
can simply drag and drop the files between projects in VSS and they will also be in sync.

59.16 How can I graphically set the tab order for controls on a form?

While MFC programmer's have had this feature available in earlier versions of Visual Studio, VB
programmers have not. To display tab orders on the active design mode Form, select the View | Tab Order
menu item. Then click the numbers on each control to reset their tab order.

59.17 How can I speed up my work in Visual Studio?

Close the Dynamic Help window unless it is something you use. Keeping it open will slow things down.

59.18 I have code snippets that I use often. How can I manage them so I can easily used them?
In Visual Studio, you can store commonly used code snippets on a tab (other than the Clipboard ring) in
your Toolbox. You use drag and drop techniques to move the snippets to the Toolbox. To later use a snippet
in your code, you drag it from the Toolbox and drop it into your code.

59.19 Can I drag and drop code snippets using the VS.NET IDE?

Yes, in Code View you can select and drag code to aTab (General Tab) in the ToolBox and then you can
drag the code from the Tab to the desired location.

59.20 In VS.NET, how can I change the build order of projects in my solution?

You can set the build order of the projects by right clicking on the Solution and choosing Project Build
Order and adjusting the dependencies on the Dependencies tab in the Project Dependencies window that
pops up.

59.21 In VS.NET, how can I specify the start up project for my application?

In the Solution Explorer right click on the project that should be the start up project for your application
and choose the Set As Start Up Project option.

59.22 If I create an assembly, how can I see the assembly/components from with the VS.Net "Add..."
dialogs?

There are two ways in which this can be done. The first way is to use the provided Public assembly folder
that is installed with VS.Net.

This folder is: "C:\Program Files\Microsoft Visual Studio .NET\Common7\IDE\PublicAssemblies"

All assemblies in this folder will be picked up by the "Add Reference" dialog under the ".NET" tab, and the
"Customize Toolbox" under the ".NET Framework Components" tab.

Now, you are not limited to using this folder. You can specify your own public assembly folder by adding a
key to the registry.

If you look at the following key:


"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\AssemblyFolders", you will see a
subkey named "PublicAssemblies". This is where the path above is specified as a public assembly folder.
To add your own folder, create a key (e.g. MyAssemblies), and set the default value to be the desired path.
59.23 How does VS.Net find the referenced assemblies when I build a project from the command line?

There are a couple of ways to specify where VS.Net looks for the assemblies that you reference in your
project when building from the command line.

One way is to specify the "HintPath" for the reference:

<Reference
Name = "MyAssembly.dll"
AssemblyName = "MyAssembly.dll"
HintPath = "..\work\samples\assemblies\MyAssembly.dll"
/>

However, this would require all of the systems that build the application to have the exact same directory
structure locally. There are often times when this is not wanted (or needed), such as having a script on a
build machine.

In this type of situation, you can use the DEVPATH environment variable, or make use of the Public
Assembly folder functionality

To use the DEVPATH environment variable, you would simply add the folder that contains the assembly
(e.g. "c:\work\samples\assemblies") to the list of directories. Then, you will need to specify the
<developmentMode> element in the machine configuration file:

<configuration>
<runtime>
<developmentMode developerInstallation="true">
</runtime>
</configuration>

This will instruct the CLR to locate the assemblies based on the DEVPATH environment variable.

A less restrictive way to specify the assembly locations is by making use of the Public Assembly Folder
functionality. This is done by adding a path to the PublicAssemblies registry key.

Open up the registry, and locate the


"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.0\AssemblyFolders" key (for
VS.Net 2003, you would look under the "...\VisualStudio\7.1\AssembliesFolders" key). You will see a
subkey named "PublicAssemblies". This is where you will want to add additional keys to create your own
Public folders. To add your own folder, create a key (e.g. MyAssemblies), and set the default value to be
the desired path (e.g. "c:\work\samples\assemblies").

The option you choose will simply depend on your needs.

59.24 How can I get the default namespace of a C# project in VS.NET?


To get the default namespace of a C# project developed using VS.NET, you need to right-click on the
project in the Solution Explorer and then choose Properties->Common Properties->General->Default
Namespace

59.25 How can I open a project created with Visual Studio .NET 2003 in Visual Studio .NET 2002?

Check out the following article in CodeProject : A Utility to Convert VS.NET 2003 Project Files.

59.26 How can I change the Word Wrap Property of VS.NET IDE?

You need to go to Tools->Options->Text Editor->All Languages->General->Word Wrap and check/uncheck


the checkbox or you could press Ctrl+R Ctrl+R to toggle this property.

60. VS.NET Debugging FAQ Home


60.1 How can I see debug/trace statements when I run my application in debug mode?
60.2 Can I trace the caught Exception without breaking into the debugger?
60.3 How do I conditionally include certain methods based on some preprocessor defines?
60.4 What is fuslogvw.exe?
60.5 How do I set the debugger to Break on Exception?
60.6 If I have a user control and a designer, how can I debug the designer?
60.7 How can I use the debugger paint and focus problems as the stops are always hit too early?
60.8 In a debug build, how do I write debug information to the output window (similar to the TRACE
macro from VC6)?
60.9 Why am I getting dupllicate trace messages for my trace statements?
60.10 How can I direct debug output to a text file?
60.11 Can I trace the Call Stack at any particular point without breaking into the debugger?

60.1 How can I see debug/trace statements when I run my application in debug mode?

When your application is launched from the VS.NET IDE in Debug mode, you will see all trace and debug
messages in the Output window calling:

60.2 Can I trace the caught Exception without breaking into the debugger?

Yes, there are framework classes that will give you the Call Stack information at a particular point.

[C#]
public static void TraceExceptionCatched(Exception e)
{
StackTrace st = new StackTrace(1, true);
StackFrame sf = st.GetFrame(StackTrace.METHODS_TO_SKIP);
if (sf != null)
{
MethodBase mb = sf.GetMethod();
Trace.WriteLine(e.ToString());
StringBuilder sb = new StringBuilder();
sb.Append("catched in File ");
sb.Append(sf.GetFileName());
sb.Append(", line ");
sb.Append(sf.GetFileLineNumber());
Trace.WriteLine(sb.ToString());
sb = new StringBuilder();
sb.Append("in method ");
sb.Append(mb.ReflectedType.Name);
sb.Append(".");
sb.Append(mb.Name);
sb.Append("(");
bool first = true;
foreach (ParameterInfo pi in mb.GetParameters())
{
if (!first)
sb.Append(", ");
first = false;
sb.Append(pi.ParameterType.Name);
sb.Append(" ");
sb.Append(pi.Name);
}
sb.Append(");");
Trace.WriteLine(sb.ToString());
}
}

You could then call this method from the Catch portion of a try/catch block.

60.3 How do I conditionally include certain methods based on some preprocessor defines?

You have the regular #if and #else preprocessor directive inside which you could place your code. Take a
look at the "C# Preprocessor Directives" section for the complete list of preprocessor directives.

There is also a concept of "Conditonal Methods" that will let you declare some methods as conditional
methods based on the presence of certain preprocessor directives, using the ConditionalAttribute. Then the
compiler will not only ignore the method, but also the method-call if the preprocessor symbol is not
defined. Take a look at this MSDN section for more information:
Conditional Methods Tutorial

60.4 What is fuslogvw.exe?

When the system fails to locate an assembly, it generates a log file. Fuslogvw.exe is the viewer program
that gives you access to this log. You can run this tool from a command line. This log information helps you
diagnose why the .NET Framework cannot locate an assembly at run time.

60.5 How do I set the debugger to Break on Exception?

1) In VS.NET go to the Debug Menu >> "Exceptions..." >> "Common Language Runtime Exceptions" >>
"System" and select "System.NullReferenceException"

2) In the botton of that dialog there is a "When the exception is thrown:" group box, select "Break into the
debugger"

3) Run your scenario. When the exception is thrown, the debugger will stop and notify you with a dialog
that says something like:
"An exception of type "System.NullReferenceException" has been thrown.
[Break] [Continue]"

Hit [Break]. This will put you on the line of code that's causing the problem.

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

60.6 If I have a user control and a designer, how can I debug the designer?

You need to use a second instance of VS.NET to debug the one that's running the code.

1) Put your control on a form in VS.NET


2) Start a 2nd Vs.Net
3) Choose the Debug menu >> Processes ...
4) Double click "devenv.exe" and choose "Common Language Runtime" as the types
of debugging
5) Open your code file, set your breakpoint, and you're debugging.

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

60.7 How can I use the debugger paint and focus problems as the stops are always hit too early?
Using dual monitors is one way to tackle this probllem, but If you happen to be running on a terminal
server machine there's an even better way to do this. Create a terminal server session to your own machine
and start the exe in the terminal server window. Start the debugger on the console window and attach it to
the exe in the other session. This is helpful if you're debugging paint/focus issues because then the
debugger won't steal focus from your app when a breakpoint gets hit.

(from sburke_online@microsoft..nospam..com on microsoft.public.dotnet.framework.windowsforms)

60.8 In a debug build, how do I write debug information to the output window (similar to the TRACE
macro from VC6)?

You can use the Console.Write and Console.WriteLine methods from within a Windows Forms project to
do this. The class DefaultTraceListener is used to implement this functionality. When your application is
launched from the VS.NET IDE in Debug mode, you will see all trace and debug messages in the Output
window by calling:

System.Diagnostics.Trace.WriteLine()
or
System.Diagnostics.Debug.WriteLine()

60.9 Why am I getting dupllicate trace messages for my trace statements?

This is possible if the same listener was added more than once to the Listeners list in Trace. This is possible
even if an assembly that you linked do makes an additional entry for the same listener.

Perform a check like this before adding a listener.

if(Trace.Listeners.Count == 0)
{
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
Trace.AutoFlush = true;
Trace.Indent();
}

60.10 How can I direct debug output to a text file?

You need to add a Trace Listener to your code. Below is sample code that adds a TextWriterTraceListener
(and don't forget the Flush before you terminate). For more information on tracing in general, look for the
topic "Tracing Code in an Application" in your online .NET documentation.

//set up the listener...


System.IO.FileStream myTraceLog = new System.IO.FileStream(@"C:\myTraceLog.txt",
System.IO.FileMode.OpenOrCreate);
TextWriterTraceListener myListener = new TextWriterTraceListener(myTraceLog);
..........
//output to the instance of your listener
myListener.WriteLine( "This is some good stuff");
...........
//flush any open output before termination... maybe in an override of your form's OnClosed
myListener.Flush();

60.11 Can I trace the Call Stack at any particular point without breaking into the debugger?

Yes, there are classes in the framework that will provide you call stack information that you can trace to the
output:

[C#]
public static void TraceCallStack()
{
StackTrace st = new StackTrace(1, true);
StackFrame sf = st.GetFrame(StackTrace.METHODS_TO_SKIP);
if (sf != null)
{
MethodBase mb = sf.GetMethod();
StringBuilder sb = new StringBuilder();
sb.Append(mb.ReflectedType.Name);
sb.Append(".");
sb.Append(mb.Name);
sb.Append("(");
bool first = true;
foreach (ParameterInfo pi in mb.GetParameters())
{
if (!first)
sb.Append(", ");
first = false;
sb.Append(pi.ParameterType.Name);
sb.Append(" ");
sb.Append(pi.Name);
}
sb.Append(");");

int n = StackTrace.METHODS_TO_SKIP+1;
sf = st.GetFrame(n);
if (sf != null)
{
sb.Append(" called from ");

do
{
mb = sf.GetMethod();
sb.Append(mb.ReflectedType.Name);
sb.Append(".");
sb.Append(mb.Name);
sb.Append(":");
sf = st.GetFrame(++n);
}
while (sf != null);

Trace.WriteLine(sb.ToString());
}
}

61. VS.NET Macros FAQ Home


61.1 Can VB.NET code be formatted using macros?
61.2 Is it possible to call macros as part of a Visual Studio.NET command line build (or from a batch
file)?

61.1 Can VB.NET code be formatted using macros?

VB.NET can perform decent autoformatting for code that may not be properly formatted. Here is a macro
that can call this Auto Formatting command for all the files in a project.

Grab utils.zip.

61.2 Is it possible to call macros as part of a Visual Studio.NET command line build (or from a batch file)?

Yes. You just use the following syntax:

devenv.exe {Solution Name} /command {Macro name}

Example:

devenv.exe "myproject.sln" /command "Macros.Syncfusion.Utils.FormatProjectAndClose"


Dev studio will start up, load the solution, run the macro and then terminate.

Be sure to check that devenv.exe is available from your command line. Normally, you just have to run
VSVARS32.bat to ensure this if you do not already have this in your path.

62. Framework Tips General FAQ Home


62.1 How can I catch an exception on a program wide basis?
62.2 Can I generate UML diagrams from C# code?
62.3 Is it possible to turn off strong name validation for an assembly?
62.4 Does .Net support "deprication" as in Java?
62.5 Is there any way to Shutdown/Restart Windows using .NET?
62.6 Can .NET applications run on non Microsoft Platforms?
62.7 Can I play audio and video files using .NET?
62.8 Can I create file associations with .NET?
62.9 How can I Invoke a private interface implementations of an instance using reflection?
62.10 How can I adjust the version number for multiple projects without changing every
AssemblyInfo.cs file constantly?
62.11 How do I launch IE or any other process from code?
62.12 How do I pre-JIT an assembly to native code during installation?
62.13 How do I get the install directory for the version of the runtime that is loaded in the current
process?
62.14 How to retrieve the assembly version, name, etc. contained in the "AssemblyInfo.cs", from inside
the running app?
62.15 Is there a way to access private and protected members of a class instance?
62.16 In VB.NET how do I access the runtime type object of a specified type from it's type name?
62.17 How do I print a doument using .NET?

62.1 How can I catch an exception on a program wide basis?

You can handle the Application.ThreadException event. See the FrameWork class library for a more
detailed sample in both VB abd C#.

[STAThread]
public static void Main()
{
Application.ThreadException += new
System.Threading.ThreadExceptionEventHandler(UnhandledExceptionCatcher);
Application.Run(new Form1());
}

private static void UnhandledExceptionCatcher(object sender,


System.Threading.ThreadExceptionEventArgs e)
{
Console.WriteLine("caught an unhandled exception.");
}

62.2 Can I generate UML diagrams from C# code?

There are several commercial products that support this. Take a look at Metamill and WithClass

62.3 Is it possible to turn off strong name validation for an assembly?

You can turn off strong name validation for an assembly by using the sn.exe utility that ships with the
framework.

The command line is:


sn -Vr assemblyname

This is helpful if you want to add an assembly to the GAC that is delay signed.

62.4 Does .Net support "deprication" as in Java?

Yes, use the Obsolete attribute on the property, method, etc. You can also provide some deprecation
message when you specify this attribute.

62.5 Is there any way to Shutdown/Restart Windows using .NET?

Take a look at classes available here: http://www.mentalis.org/soft/class.qpx?id=7.

62.6 Can .NET applications run on non Microsoft Platforms?

Check out the Mono Project.

http://www.go-mono.com/

62.7 Can I play audio and video files using .NET?

You cannot directly do this using .NET. However, there are some wrapper classes available at
http://www.mentalis.org/soft/class.qpx?id=1 that allow you to do just this. You can download the latest
version of these classes directly from the site.
We have packaged these classes as a library and added a simple Winforms sample and made these available
here.

This library basically uses the Media Control Interface (MCI). More details are available here and in
several other places.

62.8 Can I create file associations with .NET?

Please take a look at classes available here: http://www.mentalis.org/soft/class.qpx?id=5.

62.9 How can I Invoke a private interface implementations of an instance using reflection?

Make sure to preface the method/property name with the fully qualified interface name that it belongs to,
like this:

// In C#
// Where someType implements ISomeInterface's SomeMethod as a private implementation.
Type someType = someInstance.GetType();
MethodInfo mi = someType.GetMethod("System.Windows.Forms.ISomeInterface.SomeMethod",
BindingFlags.NonPublic | BindingFlags.Instance);
if(mi != null)
{
mi.Invoke(someInsance, new object[]{});
}

' In VB.Net
' Where someType implements ISomeInterface's SomeMethod as a private implementation.
Dim someType As Type = someInstance.GetType()
MethodInfo mi = someType.GetMethod("System.Windows.Forms.ISomeInterface.SomeMethod",
BindingFlags.NonPublic | BindingFlags.Instance)
If Not mi Is Nothing Then
' Assuming no arguments for SomeMethod.
mi.Invoke(someInsance, Nothing)
End If

62.10 How can I adjust the version number for multiple projects without changing every AssemblyInfo.cs
file constantly?
The version information needs to be set with the "AssemblyVersion" attribute for each project. However,
this attribute does not need to be specified in the project's AssemblyInfo file. You can create a separate file
with the "AssemblyVersion" attribute that is shared across projects that you wish to keep in sync. This file
can either be shared via VSS, or by including the file as a link in the projects.

62.11 How do I launch IE or any other process from code?

You can do so using the System.Diagnostics.Process.Start method as follows:

// Just specifying the document name will open the appropriate app based on system settings.
Process.Start("Http://msdn.microsoft.com")
// Open a word document in Word.
Process.Start("AWordDocument.doc")
// Or open the app directly:
Process.Start()

62.12 How do I pre-JIT an assembly to native code during installation?

62.13 How do I get the install directory for the version of the runtime that is loaded in the current process?

For example, the "C:\WINNT\Microsoft.NET\Framework\v1.0.3705" dir for the 1.0 framework version.

You can do so using PInvoke to call this native API method:

[C#]
[DllImport("mscoree.dll")]
// Declaration
internal static extern void
GetCORSystemDirectory([MarshalAs(UnmanagedType.LPTStr)]System.Text.StringBuilder Buffer,
int BufferLength, ref int Length);
// Gets the path to the Framework directory.
System.Text.StringBuilder sb = new System.Text.StringBuilder(1024);
int size;
// returned value in size can be ignored
GetCORSystemDirectory(sb, sb.Capacity, ref size);

[VB.Net]
' Declaration
Private Declare Function GetCORSystemDirectory Lib "mscoree.dll" ( ByVal Buffer As
System.Text.StringBuilder, ByVal BufferLength As Integer, ByRef Length As Integer) As Integer

' Gets the path to the Framework directory.


Dim Path As New System.Text.StringBuilder(1024)
Dim Size As Integer
' returned value in Size can be ignored
GetCORSystemDirectory(Path, Path.Capacity, Size)

62.14 How to retrieve the assembly version, name, etc. contained in the "AssemblyInfo.cs", from inside the
running app?

Here is a way to do this:

1) string strVersion = Application.ProductVersion;

2) Assembly assembly = Assembly.GetCallingAssembly();


string strVersion = assembly.GetName().Version.ToString();

The Application class offers also access to additional information like ProductName and so on.

(Information provided by Holger Persch in our forums)

62.15 Is there a way to access private and protected members of a class instance?

.NET Reflection can be used to get hold of non-Public members of a class instance. The System.Type class
provides various methods that allow you to access the fields/properties/methods for all defined types.
Depending on the context, you can use either the typeof(class) operator or the Object.GetType() method to
get hold of the System.Type object representing the particular type and then use that type object to access
the required member information.

The following code shows how to use the Type.GetField() and FieldInfo.GetValue() methods to determine
the value of the 'pasteIndex' private field implemented by the Diagram.Controller class.

// In C#.NET
// Use Reflection to access the this.ActiveDiagram.Controller object's pasteIndex private member

Type typecontroller = typeof(Syncfusion.Windows.Forms.Diagram.Controller);


System.Reflection.FieldInfo finfo = typecontroller.GetField("pasteIndex", BindingFlags.Instance|
BindingFlags.NonPublic|BindingFlags.GetField);
int npasteindex = 0;
if(finfo != null)
npasteindex = (int)finfo.GetValue(this.ActiveDiagram.Controller);

' In VB.NET
' Use Reflection to access the Me.ActiveDiagram.Controller object's pasteIndex private member

Dim typecontroller As Type = GetType(Syncfusion.Windows.Forms.Diagram.Controller)


Dim finfo As FieldInfo = typecontroller.GetType().GetField("pasteIndex", BindingFlags.Instance Or
BindingFlags.NonPublic Or BindingFlags.GetField)
Dim npasteindex As Integer = 0
If Not finfo Is Nothing Then
npasteindex = finfo.GetValue(Me.ActiveDiagram.Controller)
End If

62.16 In VB.NET how do I access the runtime type object of a specified type from it's type name?

Visual Basic has a GetType operator that can be used to obtain the System.Type object for the specified
type name. This is the equivalent of the typeof keyword in C#.

' Returns the System.RuntimeType object representing the integer type.


Dim inttype As Type = GetType(Integer)

' Returns the System.RuntimeType object representing the Project1.Type1 class.


Dim mytype As Type = GetType(Project1.Type1)

62.17 How do I print a doument using .NET?

This can be done using the Process class and specifying the verb as "Print". This is the equivalent of right
clicking and selecting print in the windows shell. Here is the code snippet that prints documents like MS
Excel, MS Word, pdf etc..

// In C#.NET
//Print an Excel document
Process pr = new Process();
pr.StartInfo.Verb = "Print";
pr.StartInfo.FileName = "Sample.xls";
pr.Start();
' In VB.NET
'Print an Excel document
Dim pr As Process = New Process()
pr.StartInfo.Verb = "Print"
pr.StartInfo.FileName = "Sample.xls"
pr.Start()

63. Framework Tips Events FAQ Home


63.1 How do I intercept event subscription of a event in my base class?
63.2 How do I control the order in which events are fired to multiple subscribers?
63.3 How do I figure out if a particular client object has susbcribed to one of my events?

63.1 How do I intercept event subscription of a event in my base class?

In C# you could intercept what gets susbcribed as follows: // In a Control derived class, for example: // Use
override if the base class property was marked as virtual public new event EventHandler Click { add { //
Do not let derived classes subscribe to this event, they should instead override OnClick. if(value.Target !=
this) base.Click += value; } remove { base.Click -= value; } }

63.2 How do I control the order in which events are fired to multiple subscribers?

In C#, you can do as follows:

// Use a custom Delegate to hold your subscribers


private EventHandler myHandlers;
// Control Click event firing, for example.
public new event EventHandler Click
{
add
{
this.myHandlers += value;
}
remove
{
this.myHandlers -= value;
}
}
protected override void OnClick(EventArgs e)
{
// First let my derived classes receive the Click event.
foreach(Delegate d in this.myHandler.GetInvocationList())
{
if(d.Target == this)
{
d.DynamicInvoke(new object[]{this, e});
break;
}
}
// Then let other subscribers receive the Click event.
foreach(Delegate d in this.myHandler.GetInvocationList())
{
if(d.Target != this)
d.DynamicInvoke(new object[]{this, e});
}

63.3 How do I figure out if a particular client object has susbcribed to one of my events?

In C#, you can do as follows:

// In a Control derived class, for example, first store the handlers in a custom list.
private EventHandler myHandlers;
public new event EventHandler Click
{
add
{
this.myHandlers += value;
}
remove
{
this.myHandlers -= value;
}
}

// This method will specify whether a particular delegate is subscribed.


public bool IsSubscribed(Delegate del)
{
System.Delegate[] delegates = this.myHandlers.GetInvocationList();
foreach(Delegate d in delegates)
{
if(d == del)
return true;
}
return false;
}

// Fire the Click event by parsing through your delegate list.


protected override void OnClick(EventArgs e)
{
// First let my derived classes receive the Click event.
foreach(Delegate d in this.myHandlers.GetInvocationList())
{
d.DynamicInvoke(new object[]{this, e});
}
}

You can then find our if a delegate is subscribed as follows:

// myControl is an instance of the above derived class.


bool subscribed = this.myControl.IsSubscribed(new EventHandler(this.myControl_Clicked));

64. Framework Tips Performance FAQ Home


64.1 Is it possible to cache an assembly to improve performance?
64.2 Why are .Net programs slow to load when running under a domain?

64.1 Is it possible to cache an assembly to improve performance?

Ngen.exe allows you to install the native image of an assembly into the native image cache, resulting in
quicker loading and execution of the assembly. For example:

ngen [options] [assemblyName | assemblyPath ]

ngen MyAssembly.dll
This creates a native image for MyAssembly.dll and installs it to the native image cache.

ngen /delete MyAssembly.dll


This removes the native image from the cache.

It is also important to note that the native image must be created on the end user's machine, as it is based on
the system that creates it.

64.2 Why are .Net programs slow to load when running under a domain?
This is a known bug in 1.0. Refer to this MS KB for more information:

KB 318738

65. Framework Tips CGI FAQ Home


65.1 Can I write CGI applications using .NET?

65.1 Can I write CGI applications using .NET?

You sure can. Here is a simple CGI program that prints out the current time and also all the environment
variables that are available to it.

using System;

public class cgi


{
public static void Main(string[] args)
{
Console.WriteLine("Content-Type:text/html\n\n");

if(args.GetLength(0) == 0)
Console.WriteLine("The time now is {0}", System.DateTime.Now.ToString());
else
Console.WriteLine("Hi {0}, the time now is {1}", args[0], System.DateTime.Now.ToString());

foreach(string s in Environment.GetEnvironmentVariables().Keys)
Console.WriteLine("

{0} : {1}

",s, Environment.GetEnvironmentVariables()[s]);
}
}

66. Framework Tips General IO FAQ Home


66.1 How do you persist any object in the registry?
66.2 How can I listen to changes in a file/directory in the windows file system?
66.3 How can I convert a long path to a short path?
66.4 I want to iterate through both files and folders in a given folder. Is this possible?
66.5 My application requires a simple ini file. Is there a easy way to implement this without using any
parsing?
66.6 How can I access a webpage from a windows form?
66.7 I just want to read a text file into a string. Is there some simple code for this?
66.8 I just want to write a simple text file. Is there some simple code for this?
66.9 While deserializing how do I check whether a name is available in the deserialized info?
66.10 How come some of the objects are not initialized during deserialization?

66.1 How do you persist any object in the registry?

To store an object in the registry, the object should be serializable (either has a Serializable attribute
attached to it or derives from ISerializable; same holds to all contained objects).

ArrayList names; // Source object; Can contain any object that is serializable
... // Fill up this arraylist

BinaryFormatter formatter = new BinaryFormatter();


MemoryStream stream1 = new MemoryStream();
formatter.Serialize(stream1, names);

RegistryKey regKey;
... // Open the key where you want to store it, with write permissions
regKey.SetValue("ValueName", stream1.ToArray());

To Read from registry:


ArrayList names; // Destination object
RegKey regKey;
... // Open the corresponding key

BinaryFormatter formatter = new BinaryFormatter();


MemoryStream stream1 = new MemoryStream();

byte[] barray1 = null;


barray1 = (byte[])regKey.GetValue("ValueName");
if(barray1 != null)
{
stream1.Write(barray1, 0, barray1.Length);
MemoryStream stream1 = new MemoryStream();

byte[] barray1 = null;


barray1 = (byte[])regKey.GetValue("ValueName");
if(barray1 != null)
{
stream1.Write(barray1, 0, barray1.Length);
stream1.Position = 0;
names = formatter.Deserialize(stream1) as ArrayList;
}

66.2 How can I listen to changes in a file/directory in the windows file system?
Use FileSystemWatcher to watch for changes in a specified directory. You can watch for changes in files
and subdirectories of the specified directory. The component can watch files on a local computer, a network
drive, or a remote computer.

66.3 How can I convert a long path to a short path?

There is no direct support in the framework to do this. You have to use the GetShortPathName function
using PInvoke.

This is how the signature for this function looks like:

[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]


public static extern int GetShortPathName(string longPath,
[MarshalAs(UnmanagedType.LPTStr)]StringBuilder ShortPath, [MarshalAs(UnmanagedType.U4)]int
bufferSize);

Download C# Sample GetShortPathName.zip


Download VB.NET sample GetShortPathName_VB.zip

66.4 I want to iterate through both files and folders in a given folder. Is this possible?

Yes

string[] contents = Directory.GetFileSystemEntries("folderName");


foreach(string s in contents)
Console.WriteLine(s);

66.5 My application requires a simple ini file. Is there a easy way to implement this without using any
parsing?

Yes. This may not be the most efficient way to read from a ini file but it is a pretty good solution that is
easy to maintain.

You can use a XML file to store your settings. Use a DataSet to read from it. Consider a simple sample file,
config.ini. It has three parameters base_path, update_path and output_file. These will map to columns in
the settings datatable.

view config.ini
// add error handling
DataSet ds = new DataSet();
ds.ReadXml("config.ini", XmlReadMode.Auto);

DataTable table = ds.Tables["settings"];


DataRow row = table.Rows[0];

string baseFolder = (string)row["base_path"];


string updateFolder = (string)row["update_path"];
string outputFileName = (string)row["output_file"];

You can of course use XmlReader, XmlDocument etc to create and maintain more complex ini files. But
this is a quick way to maintain a simple property set.

66.6 How can I access a webpage from a windows form?

Use the WebRequest class found in the System.Net namespace.

//create the request object


WebRequest req = WebRequest.Create(@"http://www.syncfusion.com");

//get the response and use the reponse


WebResponse resp = req.GetResponse();
Stream stream = resp.GetResponseStream();
StreamReader sr = new StreamReader(stream);
string s = sr.ReadToEnd();
textBox1.Text = s;

66.7 I just want to read a text file into a string. Is there some simple code for this?

The following code reads a text file into a string object. It doesn't get any simpler than this. In production
code always make sure that you handle exceptions.

using System.IO;
....
// filePath should contain the complete path to a file.
StreamReader stream = new StreamReader(filePath);
fileText = stream.ReadToEnd();
stream.Close();
66.8 I just want to write a simple text file. Is there some simple code for this?

It doesn't get any simpler than this. In production code always make sure that you handle exceptions.

using System.IO;
....
// filePath has the complete path to the file
StreamWriter writer = new StreamWriter(filePath);
writer.Write(fileNewText);
writer.Close();

66.9 While deserializing how do I check whether a name is available in the deserialized info?

This is usualy an issue when a newer version introduces newer names, then the older version will not
serialize property due to the absence of certain names. For example, this code will fail, sometimes:

protected MyClassConstructor(SerializationInfo info, StreamingContext context)


{
...
// This might fail if MyProp was added in a newer version and you are serializing an older version.
this.MyProp = info.GetBoolean("MyProp");
}

To avoid such conflicts, you could insert version nos. into the serialized info. and during deserialization
check for a name only when a particular version is being deserialized. Or you could insetad parse through
the available info in the SerializationInfo list as follows:

[C#]
protected MyClassConstructor(SerializationInfo info, StreamingContext context)
{
foreach(SerializationEntry entry in info)
{
switch(entry.Name)
{
case "MyProp":
// This will make sure that older versions without the MyProp name will also deserialize without
any problems
this.MyProp = (bool)entry.Value;
break;
...
}
}

[VB.Net]
Protected MyClassConstructor(ByVal info As SerializationInfo, ByVal context As StreamingContext) As
Protected
Dim entry As SerializationEntry
For Each entry In info
Select Case entry.Name
Case "MyProp"
' This will make sure that older versions without the MyProp name will also deserialize without
any problems
Me.MyProp = (Boolean)entry.Value
Exit For

End Select
Next

End Function

66.10 How come some of the objects are not initialized during deserialization?

This is possible in this case: Say your object graph contains an object A, which has a reference to the object
B. Then while deserializing A, the reference B might not be initialized yet. This is because while
deserializing, references are deserialized one at a time and when A is deserialized, B might not have been
deserialized, yet. You should follow the workaround as follows:

[C#]
protected MyCustomConstrucotr(SerializationInfo info, StreamingContext context)
{
this.cachedRefToB = (B)info.GetValue("B", typeof(B));
// At this point cachedRefToB might not be initialized.
}
// But when this method gets called, after complete serialization, the cachedRefToB will be initialized
void IDeserializationCallback.OnDeserialization(object sender)
{
// At this point cachedRefToB will be initialized.
}
[VB.Net]
protected MyCustomConstrucotr(ByVal info As SerializationInfo, ByVal context As StreamingContext) As
Protected
Me.cachedRefToB = CType(info.GetValue("B", Type.GetType(B)), B)
' At this point cachedRefToB might not be initialized.
End Function

' But when this method gets called, after complete serialization, the cachedRefToB will be initialized
' Your class should implement IDeserializationCallback
Sub OnDeserialization(ByVal sender As Object) as IDeserializationCallback.OnDeserialization
' At this point cachedRefToB will be initialized.
End Sub

67. Framework Tips Strings FAQ Home


67.1 How to I introduce culture information into formatted strings?
67.2 How do I convert a string to an double or int?
67.3 How can I convert the string "Red" into the color Color.Red, and vice versa?
67.4 Is there a .Net way of deciding whether a string is numeric or not?
67.5 How can I determine if a string is a valid date?
67.6 How can I convert an Enumeration member to string and vice-versa?
67.7 My program dynamically builds lots of strings. Is there a way to optimize string performance?
67.8 I hate string processing. Is there an easier way to do string manipulation?
67.9 How do I use the CSV clipboard format supported by Excel?
67.10 Is there a easy way to test Regular Expressions?

67.1 How to I introduce culture information into formatted strings?

You use the CultureInfo class found in the System.Globalization namespace.

DateTime dt = DateTime.Now;

textBox2.Text = dt.ToString("D", new CultureInfo("de-DE"));


textBox3.Text = dt.ToString("D", new CultureInfo("fr-FR"));

67.2 How do I convert a string to an double or int?

One way is to use static members of the Convert class in the System namespace.

textBoxResult.Text = Convert.ToString(Convert.ToDouble(textBox1.Text) *
Convert.ToDouble(textBox2.Text));
67.3 How can I convert the string "Red" into the color Color.Red, and vice versa?

You can use the TypeDescriptor class to handle this.

Color redColor = (Color)TypeDescriptor.GetConverter(typeof(Color)).ConvertFromString("Red");


string redString = TypeDescriptor.GetConverter(typeof(Color)).ConvertToString(Color.Red);

You can also use code such as

System.Drawing.ColorConverter ccv = new System.Drawing.ColorConverter();


this.BackColor = (Color) ccv.ConvertFromString("Red");

67.4 Is there a .Net way of deciding whether a string is numeric or not?

VB.NET has a IsNumeric method that you can use to recognize a Short, Integer, Long, Decimal or Single
numeric type. From C#, you can use try/catch to look for a particular numeric type.

//long for a Single


Single num;
try
{
num = Single.Parse(someString);
}
catch (Exception e)
{
// if this is hit, someString is not a Single
}

67.5 How can I determine if a string is a valid date?

You can use the static DateTime.Parse or DateTime.ParseExact and catch any exceptions.

System.DateTime myDateTime;
bool isValid = true;
try
{
myDateTime = System.DateTime.Parse(strMyDateTime);
}
catch (Exception e)
{
isValid = false;
}

67.6 How can I convert an Enumeration member to string and vice-versa?

To convert an enum to string, do this:

string enumEntryAsString = Enum.GetName(typeof(TabSizeMode), TabSizeMode.FillToRight);

To convert a string to an enum type:

// Enclose this code within try/catch.


TabSizeMode sizeMode = Enum.Parse(typeof(TabSizeMode), "1");
(or)
TabSizeMode sizeMode = Enum.Parse(typeof(TabSizeMode), "FillToRight");

67.7 My program dynamically builds lots of strings. Is there a way to optimize string performance?

Use the StringBuilder class to concatenate strings. This class reuses memory. If you add string members to
concatenate them, there is extra overhead as new memory is allocated for the new string. If you do a series
of concatenations using the strings (instead of StringBuilder objects) in a loop, you continually get new
strings allocated. StringBuilder objects allocate a buffer, and reuse this buffer in its work, only allocating
new space when the initial buffer is consumed. Here is a typical use case.

StreamReader sr = File.OpenText(dlg.FileName);
string s = sr.ReadLine();
StringBuilder sb = new StringBuilder();
while (s != null)
{
sb.Append(s);
s = sr.ReadLine();
}
sr.Close();
textBox1.Text = sb.ToString();

67.8 I hate string processing. Is there an easier way to do string manipulation?


.NET has excellent support for Regular Expressions. Get the excellent "Regular Expressions with .NET ",
e-book by Dan Appleman. It has all that you need to get started.

Regular expressions really make string processing easier.

There are expressions that you can find on the web for everything from validating dates to phone numbers.
There are several available at this site:

http://regxlib.com/

67.9 How do I use the CSV clipboard format supported by Excel?

In this case, the dataobject is a memory stream. Here are code snippets that allow you to get/set CSV values
from/to the clipboard in a manner compatible with Excel.

[C#]
private void GetCSVFromClipBoard_Click(object sender, System.EventArgs e)
{
IDataObject o = Clipboard.GetDataObject();
if(o.GetDataPresent(DataFormats.CommaSeparatedValue))
{
StreamReader sr = new StreamReader((Stream) o.GetData(DataFormats.CommaSeparatedValue));
string s = sr.ReadToEnd();
sr.Close();
Console.WriteLine(s);
}
}

private void CopyCSVToClipBoard_Click(object sender, System.EventArgs e)


{
String csv = "1,2,3" + Environment.NewLine + "6,8,3";
byte[] blob = System.Text.Encoding.UTF8.GetBytes(csv);
MemoryStream s = new MemoryStream(blob);
DataObject data = new DataObject();
data.SetData(DataFormats.CommaSeparatedValue, s);
Clipboard.SetDataObject(data, true);
}

[VB.NET]
Private Sub GetCSVFromClipBoard_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim o As IDataObject = Clipboard.GetDataObject()
If Not o Is Nothing Then
If (o.GetDataPresent(DataFormats.CommaSeparatedValue)) Then
Dim sr As New StreamReader(CType(o.GetData(DataFormats.CommaSeparatedValue), Stream))
Dim s As String = sr.ReadToEnd()
sr.Close()
Console.WriteLine(s)
End If
End If
End Sub 'GetCSVFromClipBoard_Click

Private Sub CopyCSVToClipBoard_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button2.Click
Dim csv As String = "1,2,3" + Environment.NewLine + "6,8,3"
Dim blob As Byte() = System.Text.Encoding.UTF8.GetBytes(csv)
Dim s As New MemoryStream(blob)
Dim data As New DataObject()
data.SetData(DataFormats.CommaSeparatedValue, s)
Clipboard.SetDataObject(data, True)
End Sub 'CopyCSVToClipBoard_Click

67.10 Is there a easy way to test Regular Expressions?

There are several tools that allow you to quickly test your regular expressions. Listed below are two that we
use:

Expresso on CodeProject
RegexDesigner on SellsBrothers.com

68. Framework Tips 1.1 FAQ Home


68.1 What's new in the 1.1 framework?
68.2 Is EnableVisualStyles method to support XP styles in my app broken?
68.3 How come I don't get to see the full call stack while debugging in VS2003?

68.1 What's new in the 1.1 framework?

This MSDN article by Chris Sells provides a good introduction to the 1.1 framework:

http://msdn.microsoft.com/msdnmag/issues/03/03/WindowsForms/default.aspx

For a list of breaking changes in 1.1: http://www.gotdotnet.com/team/changeinfo/default.aspx

We will include more information here that is not covered in the above article. Please email any more info.
you have to winformsfaq@syncfusion.com

After preliminary testing, it seems like the reordering of tab pages in the TabControl by the design
time seems to be fixed.

Why do I have to use the STAThread attribute for my main method in my app.?
What are some common gotchas while trying to embed a Windows Forms Control in IE?

68.2 Is EnableVisualStyles method to support XP styles in my app broken?

Microsoft has confirmed that calling EnableVisualStyles in the main method resulting in some ImageList
corruption is a bug. There however seems to be a workaround posted by Martin Robins in the newsgroup
which worksaround this issue:

public virtual void Main() {


Application.EnableVisualStyles();
// Calling DoEvents after the above method call seems to fix this issue:
Application.DoEvents();
Application.Run(new Form1());
}

68.3 How come I don't get to see the full call stack while debugging in VS2003?

In VS2003, debug info for unmanaged code is turned off by default. This is why you will not see the call
stack including code in the System dlls. To enable debuggin for unmanaged code go to your project

properties dialog and turn on as shown in the image below: Turning On Unmanaged code debugging

69. Framework Tips Threading FAQ Home


69.1 Why do I have to use the STAThread attribute for my main method in my app.?
69.2 When I close my application, my secondary thread does not exit.
69.3 I call invoke Abort on my threads, but they still do not terminate.

69.1 Why do I have to use the STAThread attribute for my main method in my app.?

While the STAThread is required (as the documentation states) and pertinent only to applications that use
COM interop, 1.0 version of the .Net framework has some bugs that makes it necessary for you to specify
the STAThread attribute:

1) Ole Drag Drop will not work without STA. You can check this by turning on drag and drop in a form and
try to run it.

2) Invoking a method in a type using Reflection will not work either.


These bugs have however been resolved in the 1.1 version of the framework (Everett). Which means you
then do not have to specify this attribute for your main method.

69.2 When I close my application, my secondary thread does not exit.

In most cases, this can be resolved by making the thread a background thread through it's IsBackground
property.

By default, managed threads are created as foreground threads, while unmanaged threads are created as
background threads. When all of the foreground threads in an application have terminated, the CLR
invokes Abort on the background threads that are still running.

69.3 I call invoke Abort on my threads, but they still do not terminate.

There are several possible reasons for this.

Invoking Abort on a suspended thread will have no effect until the thread is resumed. Once it is resumed,
then the Abort will be carried out.

Also, when closing your application, you can make sure that the secondary threads are terminated by
calling Join (myWorkerThread.Join) immediately after invoking Abort on the thread. For instance, this
would be necessary if the thread is in the middle of an intensive operation, or even if it is simply sleeping.

70. Framework Tips XML FAQ Home


70.1 How do I add an XmlNode from one XmlDocument to an XmlNode in another XmlDocument?

70.1 How do I add an XmlNode from one XmlDocument to an XmlNode in another XmlDocument?

The XmlNode.AppendChild restricts you to add XmlNodes originated in the same XmlDocument. So, to
do the above, here is a sample workaround:

[C#]
// destParent and sourceParent are from different XmlDocuments.
// This method will append the children of sourceParent to the destParent's children.
public static void TransferChildren(XmlDocument destDoc, XmlNode destParent, XmlNode
sourceParent)
{
// Create a temporary element into which we will add the children.
XmlElement tempElem = destDoc.CreateElement("Temp");
tempElem.InnerXml = sourceParent.InnerXml;

foreach(XmlNode node in tempElem.ChildNodes)


destParent.AppendChild(node);
}

[VB.Net]
' destParent and sourceParent are from different XmlDocuments.
' This method will append the children of sourceParent to the destParent's children.
Public Static Sub TransferChildren(ByVal destDoc As XmlDocument, ByVal destParent As
XmlNode, ByVal sourceParent As XmlNode)
' Create a temporary element into which we will add the children.
Dim tempElem As XmlElement = destDoc.CreateElement("Temp")
tempElem.InnerXml = sourceParent.InnerXml

Dim node As XmlNode


For Each node In tempElem.ChildNodes
destParent.AppendChild(node)
Next
End Sub

71. Framework Tips Math FAQ Home


71.1 Are there any libraries to do numerical analysis with .NET?

71.1 Are there any libraries to do numerical analysis with .NET?

You can get more information on numerical analysis using .NET languages at this site:
http://www.centerspace.net/resources.php.

72. Network Tips FAQ Home


72.1 How do I access an FTP server using .NET?
72.2 How do I send email using .NET?
72.3 How do I read email from a POP server using .NET?
72.4 I want to UUENCODE and decode data? Does the .NET framework have support for this?
72.5 Is there a way to Ping servers using .NET?
72.6 Is there a easy way to add Socks Proxy support?
72.7 Is there a easy way to query Whois information?

72.1 How do I access an FTP server using .NET?


There is an article on CodeProject that has code for a managed component that you can use.

FTP component on Codeproject

72.2 How do I send email using .NET?

There is a nice and free SMTP component available from Quiksoft. You can read more on this here.

Also, check out this article on Codeproject:

SMTP article on Codeproject

72.3 How do I read email from a POP server using .NET?

Check out this article on Codeproject: POP3 article on Codeproject

72.4 I want to UUENCODE and decode data? Does the .NET framework have support for this?

No, but there is some code available at the link below that you can use for this purpose:

UUDECODE and UUENCODE implementation in C#

You can also download the source files from here.

72.5 Is there a way to Ping servers using .NET?

Not directly. Take a look at classes available at http://www.mentalis.org/soft/class.qpx?id=4 to do this.

ICMP classes

72.6 Is there a easy way to add Socks Proxy support?

Take a look at classes available here: http://www.mentalis.org/soft/class.qpx?id=9.

72.7 Is there a easy way to query Whois information?

Take a look at these classes: http://www.mentalis.org/soft/class.qpx?id=10.

Anda mungkin juga menyukai