14 July 2008

Как встречают новые идеи в информатике

Я наткнулся на интересную подборку отзывов на первые публикации таких учёных как Дейкстра, Тюринг, Код, Хоар и т. д. Революционные идеи часто встречают скептические замечания о их практической пользе и простоте реализации.

13 July 2008

Context menu for column headers of .NET ListView

ListView doesn't provide ColumnHeaderMouseClick event so I had to find a workaround to display context menu for column headers. There is a way to do this by resorting to Windows API but my solution is easier.

Let's say we've got a ListView control called contentsListView and two menus: generalContextMenu and headerContextMenu. generalContextMenu should be displayed when user right-clicks on an item and headerContextMenu should be displayed when he clicks on a column header.

Set the list view's property 'ContextMenuStrip' to generalContextMenu:
contentListView.ContextMenuStrip = generalContextMenu;

Add handler for 'Opening' event of generalContextMenu:
generalContextMenuStrip.Opening += generalContextMenu_Opening;

I have played with debugger a bit and found out that contentListView.GetItemAt returns first visible item of the list even when we actually click on a column header. So, when we get some value this means we either clicked on an item or on a column header. Any list item is located below the header, so if the item Position.Y is less than MousePosition.Y then user clicked on a column header.

Here is the code for the handler:

private void generalContextMenu_Opening(object sender,
    CancelEventArgs e)
{
    Point pt = contentListView.PointToClient(new Point(MousePosition.X,
        MousePosition.Y));
    ListViewItem item = contentListView.GetItemAt(pt.X, pt.Y);
    
    // Not an item or a column header
    if (item == null)
    {
        e.Cancel = true;
        return;
    }
    
    // Is it a column header?
    if (item.Position.Y > pt.Y)
    {
        e.Cancel = true;
        headerContextMenu.Show(MousePosition);
    }
}