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

TFor 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,string instantText,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.

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 }

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); }

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

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.