| View previous topic :: View next topic |
| Author |
Message |
MaxX Senior Member


Joined: 23 Mar 2012 Posts: 311
|
Posted: Thu Apr 19, 2012 8:04 am Post subject: RMB-menu for drives in fade-list by Alt+F1 / Alt+F2 |
|
|
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).
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.  |
|
| Back to top |
|
 |
ghisler(Author) Site Admin


Joined: 04 Feb 2003 Posts: 24590 Location: Switzerland
|
Posted: Fri Apr 20, 2012 10:39 am Post subject: |
|
|
Unfortunately dropdown comboboxes do not support right clicks, sorry. _________________ Author of Total Commander
http://www.ghisler.com |
|
| Back to top |
|
 |
MaxX Senior Member


Joined: 23 Mar 2012 Posts: 311
|
Posted: Fri Apr 20, 2012 4:00 pm Post subject: |
|
|
| Why not? |
|
| Back to top |
|
 |
MVV Power Member


Joined: 03 Aug 2008 Posts: 4526 Location: Russian Federation
|
Posted: Sat Apr 21, 2012 1:32 am Post subject: |
|
|
MaxX, it is a question to M$/Borland, not to Mr. Ghisler.
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 |
|
 |
MaxX Senior Member


Joined: 23 Mar 2012 Posts: 311
|
Posted: Sat Apr 21, 2012 3:34 am Post subject: |
|
|
2MVV
So, there's nothing difficult, as I see... |
|
| Back to top |
|
 |
Horst.Epp Power Member


Joined: 06 Feb 2003 Posts: 843 Location: Germany
|
Posted: Sat Apr 21, 2012 7:50 am Post subject: Re: RMB-menu for drives in fade-list by Alt+F1 / Alt+F2 |
|
|
| 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).
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.  |
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 |
|
 |
MaxX Senior Member


Joined: 23 Mar 2012 Posts: 311
|
Posted: Sat Apr 21, 2012 8:38 am Post subject: |
|
|
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 |
|
 |
MarcinW Member

Joined: 23 Jan 2012 Posts: 140 Location: Poland
|
Posted: Sat Apr 21, 2012 11:38 am Post subject: |
|
|
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 |
|
 |
Sir_SiLvA Power Member


Joined: 06 May 2003 Posts: 2602
|
Posted: Sat Apr 21, 2012 12:04 pm Post subject: |
|
|
2MarcinW
NICE, now rewrite that for delphi 2 wich is used...
AND for Lazerus for TC64Bit... |
|
| Back to top |
|
 |
MVV Power Member


Joined: 03 Aug 2008 Posts: 4526 Location: Russian Federation
|
|
| Back to top |
|
 |
MarcinW Member

Joined: 23 Jan 2012 Posts: 140 Location: Poland
|
Posted: Sat Apr 21, 2012 2:59 pm Post subject: |
|
|
| 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 |
|
 |
MarcinW Member

Joined: 23 Jan 2012 Posts: 140 Location: Poland
|
Posted: Sat Apr 21, 2012 7:56 pm Post subject: |
|
|
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:
Regards! |
|
| Back to top |
|
 |
MaxX Senior Member


Joined: 23 Mar 2012 Posts: 311
|
Posted: Wed Apr 25, 2012 9:40 am Post subject: |
|
|
So, solution is found.
How soon we'll see this feature in TC? |
|
| Back to top |
|
 |
Sir_SiLvA Power Member


Joined: 06 May 2003 Posts: 2602
|
Posted: Wed Apr 25, 2012 12:13 pm Post subject: |
|
|
I hope more important things have more priority
(apart from the fact where is the Lazerus Solution wich is needed for TC64 ) |
|
| Back to top |
|
 |
MaxX Senior Member


Joined: 23 Mar 2012 Posts: 311
|
Posted: Thu Apr 26, 2012 3:52 am Post subject: |
|
|
2Sir_SiLvA
What can be more imprortant than this daily-needed feature? |
|
| Back to top |
|
 |
|
|
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
|
|