Total Commander Forum Index Total Commander
Forum - Public Discussion and Support
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

RMB-menu for drives in fade-list by Alt+F1 / Alt+F2
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Total Commander Forum Index -> TC suggestions (English) Printable version
View previous topic :: View next topic  
Author Message
MaxX
Senior Member
Senior Member


Joined: 23 Mar 2012
Posts: 311

PostPosted: Thu Apr 19, 2012 8:04 am    Post subject: RMB-menu for drives in fade-list by Alt+F1 / Alt+F2 Reply with quote

That's what I need -> working context menus for all drives in fade-list (list is shown by Alt+F1 / Alt+F2).
Just, we must get sth like this one:
http://savepic.su/1714899.png
Same menus we can get when click RMB on drive-buttons, but drive-buttons are taking too much workspace (when over 10 drive-letters, as I often have), which I can't give (that's why I have drive-buttons disabled).
And I have to run Explorer each time I need to RMB-ckick drive (unmount virtual, eject CDs, other commands from there). Crying or Very sad
Working RMB in fade-list is really needed function! Please, add it as soon as you can!

p.s.
We've still have time while beta-testing. Wink
Back to top
View user's profile Send private message
ghisler(Author)
Site Admin
Site Admin


Joined: 04 Feb 2003
Posts: 24602
Location: Switzerland

PostPosted: Fri Apr 20, 2012 10:39 am    Post subject: Reply with quote

Unfortunately dropdown comboboxes do not support right clicks, sorry.
_________________
Author of Total Commander
http://www.ghisler.com
Back to top
View user's profile Send private message Send e-mail Visit poster's website
MaxX
Senior Member
Senior Member


Joined: 23 Mar 2012
Posts: 311

PostPosted: Fri Apr 20, 2012 4:00 pm    Post subject: Reply with quote

Why not?
Back to top
View user's profile Send private message
MVV
Power Member
Power Member


Joined: 03 Aug 2008
Posts: 4533
Location: Russian Federation

PostPosted: Sat Apr 21, 2012 1:32 am    Post subject: Reply with quote

MaxX, it is a question to M$/Borland, not to Mr. Ghisler. Very Happy
BTW, you can choose which buttons TC won't show on drive bar: use wincmd.ini parameter DriveBarHide.

ghisler, maybe you can subclass combo box to support right-click? I think it would be nice and not so hard. You can use GetComboBoxInfo function to get handle of drop-down part of combo box in order to replace its window procedure.
_________________
VirtualPanel plugin: Temporary panel for TC (forum)
TOTALCMD.NET: TCFS2, NTLinks, CopyTree, AskParam, ConPaste, Sudo…
Back to top
View user's profile Send private message Send e-mail
MaxX
Senior Member
Senior Member


Joined: 23 Mar 2012
Posts: 311

PostPosted: Sat Apr 21, 2012 3:34 am    Post subject: Reply with quote

2MVV
So, there's nothing difficult, as I see...
Back to top
View user's profile Send private message
Horst.Epp
Power Member
Power Member


Joined: 06 Feb 2003
Posts: 846
Location: Germany

PostPosted: Sat Apr 21, 2012 7:50 am    Post subject: Re: RMB-menu for drives in fade-list by Alt+F1 / Alt+F2 Reply with quote

MaxX wrote:
That's what I need -> working context menus for all drives in fade-list (list is shown by Alt+F1 / Alt+F2).
Just, we must get sth like this one:
http://savepic.su/1714899.png
Same menus we can get when click RMB on drive-buttons, but drive-buttons are taking too much workspace (when over 10 drive-letters, as I often have), which I can't give (that's why I have drive-buttons disabled).
And I have to run Explorer each time I need to RMB-ckick drive (unmount virtual, eject CDs, other commands from there). Crying or Very sad
Working RMB in fade-list is really needed function! Please, add it as soon as you can!

p.s.
We've still have time while beta-testing. Wink

You don't need Explorer to reach the RMB context menu of drives !
Mapping a button to TC's My Computer shows you all the drives
and you can reach any context for it.
Back to top
View user's profile Send private message
MaxX
Senior Member
Senior Member


Joined: 23 Mar 2012
Posts: 311

PostPosted: Sat Apr 21, 2012 8:38 am    Post subject: Reply with quote

2Horst.Epp
But I do NOT need to open any folders. Only direct click needed.
Even more, sometimes I just can't change dir to another due to selections and other reasons.
Back to top
View user's profile Send private message
MarcinW
Member
Member


Joined: 23 Jan 2012
Posts: 142
Location: Poland

PostPosted: Sat Apr 21, 2012 11:38 am    Post subject: Reply with quote

ghisler(Author) is right - combobox control by default doesn't handle right clicks, when dropped down.

However, here comes a solution:

Code:
unit ExtendedComboBox;

{Tested with Delphi 5 and Delphi 2006}
{Tested with Win95, Win98, WinME, WinNT4, Win2k, WinXP}

interface

uses
  Windows, Messages, Forms, Classes, StdCtrls;

type
  TComboBox = class(StdCtrls.TComboBox)
  private
    FObjectInstance : Pointer;
    FDropDownWnd : HWND;
    FDropDownWndProc : Pointer;
    FHandlingDropDownContextMenu : LongWord;
    procedure SubclassedListBoxWndProc(var Message : TMessage);
  protected
    procedure WndProc(var Message : TMessage); override;
  public
    constructor Create(AOwner : TComponent); override;
    destructor Destroy; override;
  end;

implementation

uses
  Menus;

constructor TComboBox.Create(AOwner : TComponent);
begin
  FObjectInstance:=MakeObjectInstance(SubclassedListBoxWndProc);
  inherited;
end;

{Every combobox window has it's own listbox window, however, listbox window
 is not a child of combobox window. So we can't be sure that listbox window
 will be destroyed before destroying combobox - we must un-subclass listbox
 window before destroying combobox}
destructor TComboBox.Destroy;
begin
  if FDropDownWnd <> 0 then
    SetWindowLong(FDropDownWnd,GWL_WNDPROC,Integer(FDropDownWndProc));
  if FObjectInstance <> nil then
    FreeObjectInstance(FObjectInstance);
  inherited;
end;

{In order to override WM_CTLCOLORLISTBOX handler, we must override WndProc -
 because of special handling of WM_CTLCOLORLISTBOX by Delphi, "message
 WM_CTLCOLORLISTBOX" handler doesn't work}
procedure TComboBox.WndProc(var Message: TMessage);
begin
  inherited;
  with Message do
  begin
    {Grab handle of the listbox}
    if Msg = WM_CTLCOLORLISTBOX then
    if FDropDownWnd = 0 then
    begin
      FDropDownWnd:=LParam;
      FDropDownWndProc:=Pointer(SetWindowLong(FDropDownWnd,GWL_WNDPROC,Integer(FObjectInstance)));
    end;
  end;
end;

{Subclassed window procedure for listbox}
procedure TComboBox.SubclassedListBoxWndProc(var Message : TMessage);
var
  SaveDropDownWnd : HWND;
  Pt : TPoint;
  TempPt : TPoint;
  R : TRect;
  Handled : Boolean;
  PopupMenu : TPopupMenu;
  TempMsg : TMsg;
begin
  with Message do
  begin
    {Don't close listbox when displaying a popup menu}
    if Msg = WM_CAPTURECHANGED then
    if FHandlingDropDownContextMenu > 0 then
    begin
      Result:=0;
      Exit;
    end;

    SaveDropDownWnd:=FDropDownWnd;

    {Un-subclass listbox}
    if Msg = WM_DESTROY then
    begin
      SetWindowLong(FDropDownWnd,GWL_WNDPROC,Integer(FDropDownWndProc));
      FDropDownWnd:=0;
    end;

    Result:=CallWindowProc(FDropDownWndProc,SaveDropDownWnd,Msg,WParam,LParam);

    {Handle right clicks on the listbox (on the basis of TControl.WMContextMenu)}
    if Msg = WM_CONTEXTMENU then
    if Result = 0 then {if not handled yet}
    try
      Inc(FHandlingDropDownContextMenu);

      Pt:=SmallPointToPoint(TWMContextMenu(Message).Pos);
      TempPt:=Pt;
      if Pt.X >= 0 then {if not InvalidPoint(Pt) then}
      begin
        {Listbox has mouse captured, so we get mouse clicks from the whole
         screen - so don't allow to display popup menu outside listbox}
        if Windows.ScreenToClient(FDropDownWnd,TempPt) then
        if Windows.GetClientRect(FDropDownWnd,R) then
        if not PtInRect(R,TempPt) then
          Exit;
        TempPt:=ScreenToClient(Pt);
      end;

      Handled:=False;
      DoContextPopup(TempPt,Handled);
      Result:=Ord(Handled);

      if not Handled then
      begin
        PopupMenu:=GetPopupMenu;
        if PopupMenu <> nil then
        if PopupMenu.AutoPopup then
        begin
          PopupMenu.PopupComponent:=Self;
          if Pt.X < 0 then {if InvalidPoint(Pt) then}
            Pt:=ClientToScreen(Point(0,0));
          PopupMenu.Popup(Pt.X,Pt.Y);
          Result:=1;
        end;
      end;

      if GetCapture <> FDropDownWnd then {if popup menu has been displayed}
      begin
        SetCapture(FDropDownWnd);

        {Remove all waiting WM_LBUTTONDOWN messages - so closing popup menu by
         clicking left mouse button on the listbox will not close the listbox}
        while PeekMessage(TempMsg,FDropDownWnd,WM_LBUTTONDOWN,WM_LBUTTONDOWN,PM_REMOVE) do;
      end;
    finally
      Dec(FHandlingDropDownContextMenu);
    end;
  end;
end;

(******************************************************************************)

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

{If the component, which is displaying a popup menu, is a combobox,
 close its listbox when the popup menu item has been executed}
procedure TPopupListEx.WndProc(var Message : TMessage);
var
  I : Integer;
begin
  with Message do
  begin
    if Msg = WM_COMMAND then
      Result:=1; {not handled}

    inherited;

    if Result = 0 then
      Exit;
    Result:=0;

    for I:=0 to Count-1 do
    with TPopupMenu(Items[I]) do
    if FindItem(wParam,fkCommand) <> nil then
    begin
      if PopupComponent is TComboBox then
      with TComboBox(PopupComponent) do
        DroppedDown:=False;
      Break;
    end;
  end;
end;

var
  PopupListEx : TPopupListEx;
initialization
  {Replace PopupList global variable with TPopupListEx object}
  PopupListEx:=TPopupListEx.Create;
  while PopupList.Count > 0 do
  try
    PopupListEx.Add(PopupList[0]);
  finally
    PopupList.Remove(PopupList[0]); {Force DeallocateHWnd call for the last item}
  end;
  PopupList.Free;
  PopupList:=TPopupList(PopupListEx);
end.


Usage example: attach this unit _after_ StdCtrls, create combobox, assign a popup menu to the combobox and try:

Code:
procedure TForm1.ComboBox1ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean);
begin
  with Sender as TComboBox do
  if PopupMenu <> nil then
  if PopupMenu.Items.Count > 0 then
    PopupMenu.Items[0].Caption:=Text;
end;

or:
Code:
procedure TForm1.ComboBox1ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean);
begin
  with Sender as TComboBox do
  if PopupMenu <> nil then
  if PopupMenu.Items.Count > 0 then
  begin
    PopupMenu.Items[0].Caption:=Text;
    MousePos:=ClientToScreen(MousePos);
    PopupMenu.PopupComponent:=TComboBox(Sender); {important!}
    PopupMenu.Popup(MousePos.X,MousePos.Y);
    Handled:=True;
  end;
end;
Back to top
View user's profile Send private message
Sir_SiLvA
Power Member
Power Member


Joined: 06 May 2003
Posts: 2602

PostPosted: Sat Apr 21, 2012 12:04 pm    Post subject: Reply with quote

2MarcinW
NICE, now rewrite that for delphi 2 wich is used...
AND for Lazerus for TC64Bit...
Back to top
View user's profile Send private message
MVV
Power Member
Power Member


Joined: 03 Aug 2008
Posts: 4533
Location: Russian Federation

PostPosted: Sat Apr 21, 2012 2:02 pm    Post subject: Reply with quote

I think it would be simpler to write just Windows subclass procedure and use SetWindowLongPtr function to override it and send some message to parent window on mouse events... And it will be compatible with both 32/64.
_________________
VirtualPanel plugin: Temporary panel for TC (forum)
TOTALCMD.NET: TCFS2, NTLinks, CopyTree, AskParam, ConPaste, Sudo…
Back to top
View user's profile Send private message Send e-mail
MarcinW
Member
Member


Joined: 23 Jan 2012
Posts: 142
Location: Poland

PostPosted: Sat Apr 21, 2012 2:59 pm    Post subject: Reply with quote

MVV wrote:
I think it would be simpler to write just Windows subclass procedure and use SetWindowLongPtr function to override it


Have you looked at the code above for more than 2 seconds? 2/3 of this code is just subclassed window procedure, and the code installing and uninstalling it. There are many comments there - everything is explained. If you have any working code, that is simpler than the code above - feel free to put it here...

MVV wrote:
"send some message to parent window on mouse events"


Sending "some messages" directly to combobox will not work - control will NOT display a context menu, when mouse click has been fired outside the control. But we want to display context menu in the place of drop-down list (which is not a part of combobox window), so we must handle context menu manually - see code marked as "Handle right clicks on the listbox".
Back to top
View user's profile Send private message
MarcinW
Member
Member


Joined: 23 Jan 2012
Posts: 142
Location: Poland

PostPosted: Sat Apr 21, 2012 7:56 pm    Post subject: Reply with quote

Changes for Delphi 2:

1) change LongWord to Cardinal

2) declare:
Code:
type
  TWMContextMenu = packed record
    Msg: Cardinal;
    hWnd: HWND;
    case Integer of
      0: (
        XPos: Smallint;
        YPos: Smallint);
      1: (
        Pos: TSmallPoint;
        Result: Longint);
  end;


3) comment like this:
Code:

      Handled:=False;
//      DoContextPopup(TempPt,Handled);
//      Result:=Ord(Handled);


4) update Menus.pas: move TPopupList type and PopupList global variable to the interface section. Yes, I know that editing Delphi sources is not a good practice. However it's not a problem in our case:

ghisler(Author) wrote:
I made many changes already in the Delphi 2 VCL (e.g. to support Unicode windows)

http://ghisler.ch/board/viewtopic.php?p=221418#221418


Regards!
Back to top
View user's profile Send private message
MaxX
Senior Member
Senior Member


Joined: 23 Mar 2012
Posts: 311

PostPosted: Wed Apr 25, 2012 9:40 am    Post subject: Reply with quote

So, solution is found.
How soon we'll see this feature in TC?
Back to top
View user's profile Send private message
Sir_SiLvA
Power Member
Power Member


Joined: 06 May 2003
Posts: 2602

PostPosted: Wed Apr 25, 2012 12:13 pm    Post subject: Reply with quote

I hope more important things have more priority
(apart from the fact where is the Lazerus Solution wich is needed for TC64 Question)
Back to top
View user's profile Send private message
MaxX
Senior Member
Senior Member


Joined: 23 Mar 2012
Posts: 311

PostPosted: Thu Apr 26, 2012 3:52 am    Post subject: Reply with quote

2Sir_SiLvA
What can be more imprortant than this daily-needed feature?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Total Commander Forum Index -> TC suggestions (English) All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Impressum: This site is maintained by Ghisler Software GmbH

Using phpBB © 2001-2005 phpBB Group