/// <summary> /// Override of WndProc to handle the context menu or column resize on column headers. /// Necessary because ListView eats almost all mouse events, and does not provide any that can be used to handling right /// clicks in the header. /// Also couldn't use class wizard to handle WM_NOTIFY because it won't add HDN_ITEMCLICKA and HDN_DIVIDERDBLCLICKW /// </summary> /// <param name="m">The Windows Message to process</param> protected override void WndProc(ref Message m) { switch (m.Msg) { case WM_CONTEXTMENU: Point pointClicked = PointToClient(MousePosition); int index = GetColumnIndexFromMousePosition(pointClicked); if (index >= 0) { OnColumnRightClick(index, pointClicked); } break; case WM_NOTIFY: var nm = (NMHDR)m.GetLParam(typeof(NMHDR)); // Notification names: standard, ANSI (A), and Unicode (W) const int HDN_FIRST = 0 - 300; const int HDN_DIVIDERDBLCLICKA = HDN_FIRST - 5; const int HDN_DIVIDERDBLCLICKW = HDN_FIRST - 25; // Handle notifications for header column divider if (nm.code == HDN_DIVIDERDBLCLICKA || nm.code == HDN_DIVIDERDBLCLICKW) { // nmheader.iItem is in the original column order, but the resizes are done in display order. var nmheader = (NMHEADER)m.GetLParam(typeof(NMHEADER)); int inDisplayOrder = m_orderForColumnsDisplay[nmheader.iItem]; m_bv.AdjustColumnWidthToMatchContents(inDisplayOrder); } // Handle all other notifications else { base.WndProc(ref m); } break; default: base.WndProc(ref m); break; } }
const int NM_LCLICKUP = NM_FIRST - 16; // Left Click Mouse Up /// ------------------------------------------------------------------------------------ /// <summary> /// Overrides <see cref="M:System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message@)"/>. /// </summary> /// <param name="m">The Windows <see cref="T:System.Windows.Forms.Message"/> to process.</param> /// ------------------------------------------------------------------------------------ protected override void WndProc(ref Message m) { switch (m.Msg) { case WM_NOTIFY: Win32.NMHEADER nmhdr = (Win32.NMHEADER)m.GetLParam(typeof(Win32.NMHEADER)); switch (nmhdr.hdr.code) { case HDN_DIVIDERDBLCLICKW: // double-click on line between column headers. // adjust width of column to match item of greatest length. m_bv.AdjustColumnWidthToMatchContents(nmhdr.iItem); break; default: base.WndProc(ref m); break; } //Debug.WriteLine("DhListView.WndProc: WM_NOTIFY code = " + nmhdr.hdr.code); switch (nmhdr.hdr.code) { case HDN_BEGINTRACKA: case HDN_BEGINTRACKW: if (m_bv.m_xbv.Vc.HasSelectColumn) { int iCol = nmhdr.iItem; // We want to prevent the user from resizing the checkbox column (LT-3938) if (iCol == 0) { m.Result = (IntPtr)1; // Disable tracking. } } m_suppressColumnWidthChanges = true; break; case HDN_ITEMDBLCLICKW: // double-click on line between items collapses it. // However, we never get this notification, because we're not treating the // column headers as buttons. Sigh. break; case HDN_ENDTRACK: m_bv.AdjustColumnWidths(true); m_suppressColumnWidthChanges = false; break; case HDN_ITEMCHANGED: // No longer needed. HDN_DIVIDERDBLCLICKW above helps to // avoid the the problem of someone double-clicking the // separator and messing up the check mark column irretrievably. if (!m_suppressColumnWidthChanges && !m_fInAdjustWidth) { m_bv.AdjustColumnWidths(true); } break; case NM_RCLICK: // HDN_ITEMCLICK never shows up for a right click, although it does for a // left click. // NM_RCLICK shows up okay, but gives no useful information for where the // right click occurred! We have to get the current mouse position, and // compare it to the column boundaries across the window. Point pt_rclick = this.PointToClient(Control.MousePosition); int icol_rclick = GetColumnIndexFromMousePosition(pt_rclick); if (icol_rclick >= 0) { OnColumnRightClick(icol_rclick, pt_rclick); return; } break; case HDN_ENDDRAG: // We don't have a new display order until AFTER the HDN_ENDDRAG event. // so flag for further handling (on NM_CLICKUP). m_fColumnDropped = true; // flag for further handling during NM_LCLICKUP. return; case NM_LCLICKUP: // first handle the special case where the user may have dragged and dropped // something into the location of the "select column". if (m_bv.m_xbv.Vc.HasSelectColumn && m_fColumnDropped && this.ColumnOrdersOutOfSync) { this.MaintainSelectColumnPosition(); } // if displayed columns are (still) out of sync with Columns collection, // then we re-sync with that reordering and let the browse view know the new order. if (m_fColumnDropped && this.ColumnOrdersOutOfSync) { this.OnColumnDisplayReordered(); // reset our drag-n-drop event flag. m_fColumnDropped = false; } return; default: break; } break; default: base.WndProc(ref m); break; } }