Как инициирующего действия при использовании средней кнопки мыши на предметах в TPopupMenu?


Мы используем левую кнопку мыши, чтобы вызвать действия в пунктах меню TPopupMenu. Как вызвать различные действия по среднему щелчку мыши в этих пунктах меню? Другими словами, левое и среднее нажатие мыши на пункты меню TPopupmenu-это разные действия.

4   2   2011-08-06 07:45:39

4 ответа:

Глобальная переменная Menus.PopupList отслеживает все всплывающие меню и обрабатывает все массажи, отправляемые им. Вы можете переопределить этот PopupList своим собственным экземпляром следующим образом:

type
  TMyPopupList = class(TPopupList)
  private
    FMenuItem: TMenuItem;
  protected
    procedure WndProc(var Message: TMessage); override;
  end;

{ TMyPopupList }

procedure TMyPopupList.WndProc(var Message: TMessage);
var
  FindKind: TFindItemKind;
  I: Integer;
  Item: Integer;
  Action: TBasicAction;
  Menu: TMenu;
begin
  case Message.Msg of
    WM_MENUSELECT:
      with TWMMenuSelect(Message) do
      begin
        FindKind := fkCommand;
        if MenuFlag and MF_POPUP <> 0 then
          FindKind := fkHandle;
        for I := 0 to Count - 1 do
        begin
          if FindKind = fkHandle then
          begin
            if Menu <> 0 then
              Item := GetSubMenu(Menu, IDItem)
            else
              Item := -1;
          end
          else
            Item := IDItem;
          FMenuItem := TPopupMenu(Items[I]).FindItem(Item, FindKind);
          if FMenuItem <> nil then
            Break;
        end;
      end;
    WM_MBUTTONUP:
      if FMenuItem <> nil then
      begin
        GetMenuItemSecondAction(FMenuItem, Action);
        Menu := FMenuItem.GetParentMenu;
        if Action <> nil then
        begin
          Menu := FMenuItem.GetParentMenu;
          SendMessage(Menu.WindowHandle, WM_IME_KEYDOWN, VK_ESCAPE, 0);
          Action.Execute;
          Exit;
        end;
      end;
  end;
  inherited WndProc(Message);
end;

initialization
  PopupList.Free;
  PopupList := TMyPopupList.Create;

Процедуру GetMenuItemSecondAction вы должны написать сами. Возможно, этот ответ поможет добавить ваши собственные действия в компонент.

Обратите внимание, что код под WM_MENUSELECT просто скопирован из Menus.TPopupList.WndProc. Вы также можете получить MenuItem в обработке WM_MBUTTONUP с помощью MenuItemFromPoint. Но, как уже говорилось во многих комментариях: подумайте дважды (или больше), прежде чем реализовывать эту функциональность пользовательского интерфейса.

Вы не уведомлены о таком событии. Если бы Вы были там будет запись для средней кнопки мыши в списке уведомлений меню.

Так что, возможно, вы могли бы использовать какой-то Хак за спиной системы меню, если вы действительно хотите сделать это. Однако, как обсуждалось в комментариях, есть веские основания полагать, что предлагаемый вами пользовательский интерфейс может быть не очень подходящим.

Если средний щелчок не является подходящим выбором, как насчет использования некоторой комбинации клавиш с щелчком мыши, например Ctrl-Click, чтобы вызвать другое действие? TPopupMenu не имеет никакого события, связанного с настраиваемым кликом.

Это предпочтительнее, чем щелчок средней кнопкой мыши.

И тогда это гораздо проще. Просто проверьте обработчик выполнения действия, если нажата кнопка CTRL :

procedure TForm1.Action1Execute(Sender: TObject);
begin
  if (GetKeyState(VK_CONTROL) and $8000 = 0) then
    // process normal click
  else
    // process ctrl click
end;

Я пытаюсь объединить 2 ответа от автора NGLN и выйти со следующим.

Определите новый класс, унаследованный от TPopupList:

TMyPopupList = class(TPopupList)
protected
  procedure WndProc(var Message: TMessage); override;
end;

procedure TMyPopupList.WndProc(var Message: TMessage);
var H: HWND;
begin
  case Message.Msg of
    WM_MBUTTONDOWN: begin
      H := FindWindow(PChar('#32768'), nil);
      SendMessage(H, WM_IME_KEYDOWN, VK_RETURN, 0);
    end;
  end;
  inherited WndProc(Message);
end;

initialization
  PopupList.Free;
  PopupList := TMyPopupList.Create;
end.

Item1Click-это обработчик событий OnClick TMenuItem, который выполняется на основе щелчка мыши:

procedure TForm1.Item1Click(Sender: TObject);
begin
  if (GetKeyState(VK_MBUTTON) and $80 > 0) then
    Caption := 'Middle Click'
  else
    Caption := 'Normal Click';
end;

Примечание: #32768 является именем класса окна по умолчанию для всплывающего меню, см.MSDN documentation .