2012-06-29 18 views
7

Tengo un ListView con ViewStyle = vsReport y dos menús emergentes:¿Cómo configurar el menú emergente para la barra de encabezado ListView junto con el menú emergente de elementos?

  1. Columna menú emergente, que quiero abrir cuando el usuario haga clic en la barra de encabezado
  2. artículo menú emergente, debe abrirse cuando el usuario haga clic derecho en cualquier elemento/subelemento de la lista o espacio en blanco debajo de los elementos.

¿Cuál es la forma más correcta de mostrar los menús? ¿Qué eventos debo manejar?

El problema es cuando establezco la propiedad ListView.PopupMenu, aparece el menú emergente después de hacer clic derecho en cualquier punto del rectángulo del cliente de ListView.

Cuando manejo el evento ListView.OnColumnRightClick, si se activa solo después de hacer clic en el encabezado de columna, excluyendo el espacio libre de la barra de encabezado (a la derecha de las columnas).

Evento LisView.OnMouseUp incendios solamente después de un clic derecho en el espacio en blanco debajo de artículos.

+0

¿Desea que aparezca el menú emergente 'PopupMenuItems' solo cuando está sobre un elemento o incluso cuando está sobre un subelemento? – TLama

+0

@TLama sí, también en los subelementos – Andrew

Respuesta

8

Usted no tiene que utilizar la propiedad PopupMenu de la vista de lista, dejarlo desarmado y se puede conectar un controlador a OnContextPopup evento y lanzar cualquier menú emergente desea dependiendo de la posición. Ejemplo:

procedure TForm1.ListViewContextPopup(Sender: TObject; MousePos: TPoint; 
    var Handled: Boolean); 
var 
    HeaderRect: TRect; 
    Pos: TPoint; 
begin 
    GetWindowRect(ListView_GetHeader(ListView.Handle), HeaderRect); 
    Pos := ListView.ClientToScreen(MousePos); 
    if PtInRect(HeaderRect, Pos) then 
    PopupMenuColumns.Popup(Pos.X, Pos.Y) 
    else 
    PopupMenuItems.Popup(Pos.X, Pos.Y); 
end; 
+1

Batirme con eso. :-) Estaba copiando mi código de prueba del IDE para pegarlo en mi respuesta, diciendo lo mismo cuando apareció el cartel de "nueva respuesta publicada". +1. –

+0

@Ken - Me parece extraño cuando eso sucede en una pregunta de unas pocas horas, lo siento ... y gracias. :) –

+0

Es una pena para mí, tienes razón. ¡OnContextPopup! – Andrew

0

Así lo resolví, pero no me gusta esta solución. Si tiene uno mejor, por favor escriba, lo aceptaré como correcto.

uses 
    CommCtrl; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    ListView.PopupMenu := TPopupMenu.Create(Self); 
    ListView.PopupMenu.OnPopup := ListViewPopup; 
end; 

procedure TForm1.ListViewPopup(Sender: TObject); 
var 
    Pos: TPoint; 
    SrcMenu: TPopupMenu; 
    I: Integer; 
    MenuItem: TMenuItem; 
    Header: HWND; 
    HeaderRect: TRect; 
    HeaderHeight: Integer; 
begin 
    // Re-filling ListView's popup menu 
    ListView.PopupMenu.Items.Clear(); 

    // Getting header height 
    Header := ListView_GetHeader(ListView.Handle); 
    GetWindowRect(Header, HeaderRect); 
    HeaderHeight := HeaderRect.Bottom - HeaderRect.Top; 
    Pos := ListView.ScreenToClient(ListView.PopupMenu.PopupPoint); 

    // Clicked on header? 
    if Pos.Y < HeaderHeight then 
    SrcMenu := PopupMenuColumns 
    else 
    SrcMenu := PopupMenuItems; 

    // Copying destired menu to ListView.PopupMenu 
    for I := 0 to SrcMenu.Items.Count - 1 do 
    begin 
    MenuItem := TMenuItem.Create(FListViewPopupMenu); 

    with SrcMenu.Items[I] do 
    begin 
     MenuItem.Action := Action; 
     MenuItem.Caption := Caption; 
     MenuItem.ShortCut := ShortCut; 
     MenuItem.Checked := Checked; 
     MenuItem.Enabled := Enabled; 
     MenuItem.OnClick := OnClick; 
     MenuItem.HelpContext := HelpContext; 
     MenuItem.Name := Name; 
     MenuItem.ImageIndex := ImageIndex; 
    end; 

    ListView.PopupMenu.Items.Add(MenuItem); 
    end; 

    ListView.PopupMenu.Images := SrcMenu.Images; 
end; 
+0

¿Qué no le gusta de esta solución? – NGLN

+0

@NGLN Se siente un poco extraño cuando necesita copiar elementos de menú. Pensé que es posible deslizarse hacia abajo al nivel de WinAPI y hacer algo allí. – Andrew

3

Puede simplificarlo considerablemente. Crear sus dos menús emergentes (uno para la fila de encabezado y las columnas Asignar la TListView.PopupMenu el menú emergente de la columna en el IDE

Uso esto para el controlador de eventos para el ListView:..

procedure TForm1.ListView1ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); 
var 
    HeaderRect: TRect; 
    HeaderHeight: Integer; 
    Header: HWnd; 
begin 
    ListView1.PopupMenu := ColumnMenu; // Default to ColumnMenu 
    Header := ListView_GetHeader(ListView1.Handle); 
    GetWindowRect(Header, HeaderRect); 
    HeaderHeight := HeaderRect.Bottom - HeaderRect.Top; 
    if MousePos.Y < HeaderHeight then 
    ListView1.PopupMenu := HeaderMenu; 
end; 

Es un poco diferente al enfoque de @Sertac, al no llamar a ClientToScreen y PtInRect - ya que sabemos que el punto está dentro de los límites de ListView, una simple prueba de la altura del clic es suficiente para saber si estamos en el área de encabezado o columna. También garantiza que siempre haya al menos uno de los menús emergentes asignados al ListView en todo momento.

Cuestiones relacionadas