custom paste context menu fvor text boxes

  • Thread starter Dennis C. Drumm
  • Start date
D

Dennis C. Drumm

Is there a way to modify the standard context menu shown when someone right
clicks in a windows text box and that would work for all open windows
applications?



The standard context menu for a text box has 6 items, undo, cut, copy,
paste, delete and select all. I would like to add one additional paste menu
that opens a new sub menu with several optional text items that could be
pasted. The items would be populated by my program but would be available to
any other windows program when the user right clicks in a windows text box.



Thanks,



Dennis
 
S

Steven Cheng[MSFT]

Hi Dennis,

Thank you for your posting. Regarding on the issue, I am
finding proper resource to assist you and we will update as soon as posible.

Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security(This posting is provided "AS IS",
with no warranties, and confers no rights.)
 
K

Kevin Yu [MSFT]

Hi Dennis,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that you need to add a menu item to all the
TextBox context menu in windows. If there is any misunderstanding, please
feel free to let me know.

To modify the context menu of a certain TextBox, we have to handle the
WndProc function and capture the WM_CONTEXTMENU message. Here is a KB for
this:

http://support.microsoft.com/?id=224302

If we want to change all the TextBox's context menu in Windows, we have to
set a global hook. However, global hook is not supported in .NET Framework.
You cannot implement global hooks in Microsoft .NET Framework. To install a
global hook, a hook must have a native dynamic-link library (DLL) export to
inject itself in another process that requires a valid, consistent function
to call into. This requires a DLL export, which .NET Framework does not
support. Managed code has no concept of a consistent value for a function
pointer because these function pointers are proxies that are built
dynamically.

For more information, please check the following link for more information.

http://support.microsoft.com/?id=318804

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
D

Dennis C. Drumm

Thanks for the informatrion.

Another related question: I see other vendors add a context menus to various
windows, for example Nvidia adds a context menu ot the the desktop for
configuring their display adapter.

What are they doing that is so much differnet from what I want to do?? I
want to add a context menu to a windows text box.

Dennis
 
K

Kevin Yu [MSFT]

Hi Dennis,

To add a context menu for a certain window, we have to capture
WM_CONTEXTMENU message. I believe other vendors do this also in their
programs.

To change all the context menu in windows for a certain kind of control, we
have to set a global hook for the message. In .NET, there are two major
components of the library. The first part is a C# class library which you
use directly in your application. That class library, in turn, uses an
unmanaged C++ DLL internally to manage the system hooks directly.

Here is an article for more information and a sample. HTH.

http://www.codeproject.com/csharp/GlobalSystemHook.asp

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
K

Kevin Yu [MSFT]

Yes, Nice to meet you! :)

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
D

Dennis C. Drumm

Thanks Kevin,

I still havn't had time work on this, but I will soon and just wanted to let
you know I appreciate your response.

Dennis
 
B

Bruce Wood

Dennis,

There is an easier way to do what you want within the confines of the
..NET Framework. However, it isn't as far-reaching as you describe, but
then maybe you don't need such a wide-ranging solution as trapping
Windows messages would give you.

You can re-create the existing context menu in code and add items to
your re-created menu. You can then either: 1) Attach this to the text
boxes that require your new context menu, or 2) Create a sub-class of
TextBox that uses your new context menu and add that sub-class to your
forms in place of TextBox. Either way you will get a text box with what
looks like the standard context menu with one or more additional items.

Here is my code that re-creates the standard text box context menu:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace MyProject.Controls
{
/// <summary>
/// A home-grown version of the standard right-click context menu,
/// so that applications can extend this menu and add their own
/// context items.
/// </summary>
public class StandardTextBoxContextMenu : ContextMenu
{
private System.Windows.Forms.MenuItem miUndo;
private System.Windows.Forms.MenuItem miCut;
private System.Windows.Forms.MenuItem miCopy;
private System.Windows.Forms.MenuItem miPaste;
private System.Windows.Forms.MenuItem miDelete;
private System.Windows.Forms.MenuItem miSelectAll;
private System.Windows.Forms.MenuItem miSeparator;

/// <summary>
/// Creates a standard context menu for a text box, containing
/// Undo, Cut, Copy, Paste... all of the usual context menu
/// items.
/// </summary>
public StandardTextBoxContextMenu() : this(new MenuItem[0])
{ }

/// <summary>
/// Creates a standard context menu for a text box, containing
/// Undo, Cut, Copy, Paste... all of the usual context menu
/// items, with additional menu items supplied by the caller
/// that will precede the standard items in the context menu.
/// </summary>
/// <param name="additionalMenuItems">Menu items that should
/// appear above the standard menu items.</param>
/// <remarks>You can get the same effect as calling this
/// constructor by calling the no parameter constructor
/// and then using <see cref="Menu.MenuItemCollection.AddRange"/>
/// to add menu items later. Just set the <see
cref="MenuItem.Index"/>
/// property of the menu items to start numbering from
/// 0, and <see cref="Menu.MenuItemCollection.AddRange"/> will
rearrange
/// the standard menu items to follow the new ones you add.</remarks>
public StandardTextBoxContextMenu(MenuItem[] additionalMenuItems)
{
this.MenuItems.AddRange(additionalMenuItems);

InitializeComponent();
}

private void InitializeComponent()
{
this.miUndo = new System.Windows.Forms.MenuItem();
this.miSeparator = new System.Windows.Forms.MenuItem();
this.miCut = new System.Windows.Forms.MenuItem();
this.miCopy = new System.Windows.Forms.MenuItem();
this.miPaste = new System.Windows.Forms.MenuItem();
this.miDelete = new System.Windows.Forms.MenuItem();
this.miSelectAll = new System.Windows.Forms.MenuItem();
//
// miUndo
//
this.miUndo.Text = "&Undo";
this.miUndo.Click += new System.EventHandler(this.miUndo_Click);
//
// miSeparator
//
this.miSeparator.Text = "-";
//
// miCut
//
this.miCut.Text = "Cu&t";
this.miCut.Click += new System.EventHandler(this.miCut_Click);
//
// miCopy
//
this.miCopy.Text = "&Copy";
this.miCopy.Click += new System.EventHandler(this.miCopy_Click);
//
// miPaste
//
this.miPaste.Text = "&Paste";
this.miPaste.Click += new System.EventHandler(this.miPaste_Click);
//
// miDelete
//
this.miDelete.Text = "&Delete";
this.miDelete.Click += new System.EventHandler(this.miDelete_Click);
//
// miSelectAll
//
this.miSelectAll.Text = "Select &All";
this.miSelectAll.Click += new
System.EventHandler(this.miSelectAll_Click);

this.MenuItems.AddRange(
new System.Windows.Forms.MenuItem[] {
this.miUndo,
this.miSeparator,
this.miCut,
this.miCopy,
this.miPaste,
this.miDelete,
this.miSelectAll
});
this.Popup += new EventHandler(StandardTextBoxContextMenu_Popup);
}

private void miUndo_Click(object sender, System.EventArgs e)
{
// Get the text box that the context menu was popped on
if (this.SourceControl is TextBox)
{
TextBox clickedBox = (TextBox)this.SourceControl;

if (clickedBox.CanUndo)
{
clickedBox.Undo();
}
}
}

private void miCut_Click(object sender, System.EventArgs e)
{
// Get the text box that the context menu was popped on
if (this.SourceControl is TextBox)
{
TextBox clickedBox = (TextBox)this.SourceControl;

if (clickedBox.SelectionLength > 0)
{
clickedBox.Cut();
}
}
}

private void miCopy_Click(object sender, System.EventArgs e)
{
// Get the text box that the context menu was popped on
if (this.SourceControl is TextBox)
{
TextBox clickedBox = (TextBox)this.SourceControl;

if (clickedBox.SelectionLength > 0)
{
clickedBox.Copy();
}
}
}

private void miPaste_Click(object sender, System.EventArgs e)
{
// Get the text box that the context menu was popped on
if (this.SourceControl is TextBox)
{
TextBox clickedBox = (TextBox)this.SourceControl;

if (clickedBox.SelectionLength > 0)
{
clickedBox.Paste();
}
}
}

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(System.IntPtr hWnd, int msg,
int lParam, int wParam);
private const int WM_CLEAR = 0x0303;

private void miDelete_Click(object sender, System.EventArgs e)
{
// Get the text box that the context menu was popped on
if (this.SourceControl is TextBox)
{
TextBox clickedBox = (TextBox)this.SourceControl;

if (clickedBox.SelectionLength > 0)
{
SendMessage(clickedBox.Handle, WM_CLEAR, 0, 0);
}
}
}

private void miSelectAll_Click(object sender, System.EventArgs e)
{
// Get the text box that the context menu was popped on
if (this.SourceControl is TextBox)
{
TextBox clickedBox = (TextBox)this.SourceControl;
clickedBox.SelectAll();
}
}

private void StandardTextBoxContextMenu_Popup(object sender,
EventArgs e)
{
// Get the text box that the context menu was popped on
if (this.SourceControl is TextBox)
{
TextBox clickedBox = (TextBox)this.SourceControl;

// Enable and disable standard menu items as necessary
bool isSelection = clickedBox.SelectionLength > 0;
IDataObject clipObject = Clipboard.GetDataObject();
bool textOnClipboard = clipObject.GetDataPresent(DataFormats.Text);

this.miUndo.Enabled = clickedBox.CanUndo;
this.miCut.Enabled = isSelection;
this.miCopy.Enabled = isSelection;
this.miPaste.Enabled = textOnClipboard;
this.miDelete.Enabled = isSelection;
}
}
}
}
 
K

Kevin Yu [MSFT]

You're welcome, Dennis.

Thanks for sharing your experience with all the people here. If you have
any questions, please feel free to post them in the community.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top