473,382 Members | 1,657 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

alter built-in ContextMenu

I'm writing a control inheriting from ComboBox, and I'd like to add an
entry to the ContextMenu for that combo box. I have no problem if I
create an entirely new ContextMenu from scratch, but I'd prefer just to
tack my MenuItem on to the existing, built-in ContextMenu (Cut, Copy,
Paste, etc.):

_RemoveMRUItemMenu = New MenuItem
_RemoveMRUItemMenu.Text = "&Remove Item"
_RemoveMRUItemMenu.Enabled = False

MyBase.ContextMenu.MenuItems.Add(_RemoveMRUItemMen u)

AddHandler _RemoveMRUItemMenu.Click, AddressOf
RemoveCurrentMRUItem
This doesn't work; MyBase.ContextMenu returns Nothing, even though
there *is* an existing ContextMenu (the built-in one).

Is the only way to write code to manually perform the usual TextBox
context menu commands? Or can I write a ContextMenu inheriting from
something like "TextBoxContextMenu"?

Thanks,

g.

Dec 28 '05 #1
11 2632
Hi Graham,

Thanks for your post.

No, normally, there is no easy way to get this done. The default context
menu for the combobox/textbox is a win32 build-in context menu, which is
not a .Net ContextMenu class. The only way to get rid of it is supply a
..Net ContextMenu for the Control.ContextMenu property, then the .Net
ContextMenu will replace the default context menu.

I am not sure of why you do not want to use a new .Net ContextMenu to
substitute the default context menu. Actually, we can implement the default
context menu cut/copy/paste operations in the new .Net ContextMenu without
any problem. Below is a little VB.net sample:
http://www.startvbdotnet.com/controls/contextmenu.aspx

If you have any further concern, please feel free to tell me, I will work
with you. Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Dec 29 '05 #2
Brilliant, except not quite so easy to implement for the ComboBox
class, which lacks Copy(), Paste(), ... methods.

Any ideas?

Dec 29 '05 #3
Hi Graham,

Thanks for your feedback.

For Combobox, it is composited by an Edit control and a dropdownlist. So we
can first find the Edit control in the ComboBox, then do the copy/cut/paste
operations on this Edit control.

If you use Reflector to view the source code of TextBox.Cut/Copy/Paste
methods, you will see that, they simply p/invokes SendMessage API to send
WM_COPY,WM_CUT and WM_PASTE to the TextBox(Edit) control. So we can do the
same thing. Below is the sample code snippet:

Declare Function FindWindowEx Lib "user32" Alias _
"FindWindowExA" (ByVal hWnd1 As IntPtr, _
ByVal hWnd2 As IntPtr, ByVal lpsz1 As String, _
ByVal lpsz2 As String) As IntPtr
<DllImport("user32")> _
Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal msg As
Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
End Function

Const WM_COPY As Integer = 769
Const WM_CUT As Integer = 768
Const WM_PASTE As Integer = 770
Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MenuItem1.Click
Dim hEdit As IntPtr = FindWindowEx(Me.ComboBox1.Handle,
IntPtr.Zero, "Edit", String.Empty)
If hEdit.Equals(IntPtr.Zero) Then
MessageBox.Show(Marshal.GetLastWin32Error())
Else
SendMessage(hEdit, WM_COPY, 0, 0)
End If

End Sub

Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MenuItem2.Click
Dim hEdit As IntPtr = FindWindowEx(Me.ComboBox1.Handle,
IntPtr.Zero, "Edit", String.Empty)
If hEdit.Equals(IntPtr.Zero) Then
MessageBox.Show(Marshal.GetLastWin32Error())
Else
SendMessage(hEdit, WM_CUT, 0, 0)
End If

End Sub

Private Sub MenuItem3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MenuItem3.Click
Dim hEdit As IntPtr = FindWindowEx(Me.ComboBox1.Handle,
IntPtr.Zero, "Edit", String.Empty)
If hEdit.Equals(IntPtr.Zero) Then
MessageBox.Show(Marshal.GetLastWin32Error())
Else
SendMessage(hEdit, WM_PASTE, 0, 0)
End If
End Sub

It works well on my side. Hope it helps

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Dec 29 '05 #4
Jeffrey:

To make this approach robust, I had to write a class deriving from
ContextMenu that would:

1. Override OnPopup in order to selectively enable/disable MenuItems
that aren't usable. (E.g., you can't "cut" or "copy" when there's no
selected text.)

2. Handle both TextBoxBase controls and ComboBox controls, although
the method for obtaining the handle to both is different.

Now, 200ish lines later (didn't you say this would be simple? :)), I've
got a derived ContextMenu that still has these shortcomings:

1. It's not generic, requiring different handlers for TextBoxBase and
ComboBox controls (and their derivatives). I'd prefer if this class
were constructed generically (that is, if it could be applied to any
control), but I don't see how to do that, given the various methods for
obtaining the correct handle to the editable portion of the control.

2. It's not international: I'd prefer to read the values for "Cut,"
and so on, from the system's regional settings, but I've got no idea
where I'd locate those.

Here's where I am so far. Any comments would be lovely.

g.

''' <summary>
''' A context menu (derived from the System.Windows.Forms.ContextMenu
class) that
''' replicates the standard edit context menu controls (Copy, Cut,
Paste, Undo, and Select
''' All) so that the ContextMenu can be expanded upon.
''' </summary>
''' <remarks>
''' The EditContextMenu supports ComboBox and TextBoxBase controls (and
any controls
''' that derive from them).
''' <br>For more information about the development of this class,
''' contact Graham Charles (gr****@aiid.com).
''' </remarks>
''' <example>
''' To replace a control's default Win32 ContextMenu with this
expandable class, do the
''' following:
''' <code lang="VB" title="Constructor example (derived control)"
''' description="This example demonstrates how to instantiate an
aiEditContextMenu object
''' in a control that derives from ComboBox or TextBoxBase.">
''' Public Class aiComboBox
''' Inherits System.Windows.Forms.ComboBox
'''
''' Private myContext As New aiEditContextMenu(Me)
'''
''' ' ... remainder of code
''' </code>
''' <code title="Contstructor example (control on form)">
''' </code>
''' <code lang="VB" title="Adding Menu Items example"
''' description="This example demonstrates how to add a MenuItem to
the custom edit
''' context menu.">
''' ' / in declarations section
''' Private myMenuItem As MenuItem
'''
''' ' / in Form_Load or other initialization area
''' If myMenuItem Is Nothing Then
''' myMenuItem = New MenuItem("My Caption")
''' myContext.MenuItems.Add(myMenuItem)
''' AddHandler myMenuItem.Click, AddressOf myMenuItemHandler
''' End If
''' </code>
''' </example>
Public Class aiEditContextMenu
Inherits System.Windows.Forms.ContextMenu

#Region "/// Declarations "
Private Declare Auto Function GetWindow Lib "user32.dll" (ByVal
hwnd As IntPtr, ByVal wCmd As Int32) As IntPtr
Private Declare Auto Function SendMessage Lib "user32.dll" (ByVal
hwnd As IntPtr, ByVal wMsg As Int32, ByVal wParam As Boolean, ByVal
lParam As Int32) As Int32
Private Const EM_UNDO = &HC7
Private Const EM_CANUNDO = &HC6
Private Const WM_CUT = &H300
Private Const WM_COPY = &H301
Private Const WM_PASTE = &H302
Private Const WM_CLEAR = &H303
Private Const GW_CHILD As Int32 = 5
Public MenuItemCopy As New MenuItem("&Copy", New
System.EventHandler(AddressOf MenuCopy))
Public MenuItemDelete As New MenuItem("&Delete", New
System.EventHandler(AddressOf MenuDelete))
Public MenuItemPaste As New MenuItem("&Paste", New
System.EventHandler(AddressOf MenuPaste))
Public MenuItemCut As New MenuItem("Cu&t", New
System.EventHandler(AddressOf MenuCut))
Public MenuItemUndo As New MenuItem("&Undo", New
System.EventHandler(AddressOf MenuUndo))
Public MenuItemSelectAll As New MenuItem("Select &All", New
System.EventHandler(AddressOf MenuSelectAll))

Private _ComboBox As System.Windows.Forms.ComboBox ' /
ListControl object
Private _TextBoxBase As System.Windows.Forms.TextBoxBase ' /
TextBoxBase object

#End Region

#Region "/// Constructors "
''' <summary> The constructor can take a ComboBox or TextBoxBase
item as an argument. </summary>
Public Sub New(ByVal vComboBox As ComboBox)
_ComboBox = vComboBox
_ComboBox.ContextMenu = Me
AttachMenuItems()
End Sub
Public Sub New(ByVal vTextBoxBase As TextBoxBase)
_TextBoxBase = vTextBoxBase
_TextBoxBase.ContextMenu = Me
AttachMenuItems()
End Sub

Private Sub AttachMenuItems()
' / create context menu items to simulate standard ones
MyBase.MenuItems.Add(MenuItemUndo)
MyBase.MenuItems.Add("-")
MyBase.MenuItems.Add(MenuItemCut)
MyBase.MenuItems.Add(MenuItemCopy)
MyBase.MenuItems.Add(MenuItemPaste)
MyBase.MenuItems.Add(MenuItemDelete)
MyBase.MenuItems.Add("-")
MyBase.MenuItems.Add(MenuItemSelectAll)
End Sub

#End Region

#Region "/// Menu Handlers"
Private Sub MenuCopy(ByVal sender As Object, ByVal e As
System.EventArgs)
Try
If Not _ComboBox Is Nothing Then

If Len(_ComboBox.SelectedText) > 0 Then
SendMessage(GetWindow(_ComboBox.Handle, GW_CHILD),
WM_COPY, False, 0)
'Clipboard.SetDataObject(_ComboBox.SelectedText)
End If
End If
If Not _TextBoxBase Is Nothing Then _TextBoxBase.Copy()
Catch ex As Exception
' / ignore errors caused by unsupported Control types
End Try

End Sub
Private Sub MenuDelete(ByVal sender As Object, ByVal e As
System.EventArgs)
Try
If Not _ComboBox Is Nothing Then
If Len(_ComboBox.SelectedText) > 0 Then
_ComboBox.SelectedText = String.Empty
End If
If Not _TextBoxBase Is Nothing Then
If Len(_TextBoxBase.SelectedText) > 0 Then
_TextBoxBase.SelectedText = String.Empty
End If
Catch ex As Exception
' / ignore errors caused by unsupported Control types
End Try

End Sub
Private Sub MenuCut(ByVal sender As Object, ByVal e As
System.EventArgs)
Try
If Not _ComboBox Is Nothing Then
SendMessage(GetWindow(_ComboBox.Handle, GW_CHILD),
WM_CUT, False, 0)
End If
If Not _TextBoxBase Is Nothing Then _TextBoxBase.Cut()
Catch ex As Exception
' / ignore errors caused by unsupported Control types
End Try
End Sub
Private Sub MenuPaste(ByVal sender As Object, ByVal e As
System.EventArgs)
Try
If Not _ComboBox Is Nothing Then
If CanPaste() Then
_ComboBox.SelectedText =
Clipboard.GetDataObject.GetData(DataFormats.Text)
End If
End If
If Not _TextBoxBase Is Nothing Then _TextBoxBase.Paste()
Catch ex As Exception
' / ignore errors caused by unsupported Control types
End Try
End Sub
Private Sub MenuSelectAll(ByVal sender As Object, ByVal e As
System.EventArgs)
Try
If Not _ComboBox Is Nothing Then _ComboBox.SelectAll()
If Not _TextBoxBase Is Nothing Then
_TextBoxBase.SelectAll()
Catch ex As Exception
' / ignore errors caused by unsupported Control types
End Try
End Sub

Private Sub MenuUndo(ByVal sender As Object, ByVal e As
System.EventArgs)
Try
If CanUndo() Then
If Not _ComboBox Is Nothing Then
SendMessage(GetWindow(_ComboBox.Handle, GW_CHILD), EM_UNDO, False, 0)
If Not _TextBoxBase Is Nothing Then _TextBoxBase.Undo()
End If
Catch ex As Exception
' / ignore errors caused by unsupported Control types
End Try
End Sub
#End Region

#Region "/// Menu Access Flags"
Private Function CanPaste() As Boolean
CanPaste =
Clipboard.GetDataObject.GetDataPresent(DataFormats .Text)
End Function
Private Function CanUndo() As Boolean
If Not _ComboBox Is Nothing Then
CanUndo = (SendMessage(GetWindow(_ComboBox.Handle,
GW_CHILD), EM_CANUNDO, False, 0) <> 0)
End If
If Not _TextBoxBase Is Nothing Then CanUndo =
_TextBoxBase.CanUndo

End Function

#End Region

#Region "/// Overrides"
Protected Overrides Sub OnPopup(ByVal e As System.EventArgs)
Dim bCanCutCopy As Boolean
Dim bCanSelectAll As Boolean

' / enable/disable controls
If Not _ComboBox Is Nothing Then
bCanCutCopy = (Len(_ComboBox.SelectedText) > 0)
bCanSelectAll = (Len(_ComboBox.Text) > 0)
End If
If Not _TextBoxBase Is Nothing Then
bCanCutCopy = (Len(_TextBoxBase.SelectedText) > 0)
bCanSelectAll = (Len(_TextBoxBase.Text) > 0)
End If

MenuItemCopy.Enabled = bCanCutCopy
MenuItemCut.Enabled = bCanCutCopy
MenuItemDelete.Enabled = bCanCutCopy
MenuItemSelectAll.Enabled = bCanSelectAll
MenuItemPaste.Enabled = CanPaste()
MenuItemUndo.Enabled = CanUndo()

MyBase.OnPopup(e)
End Sub

#End Region

End Class

Dec 29 '05 #5
Hi Graham,

Thanks for your feedback.

Yes, I see your 2 concerns, I will provided some comment below:

#1, Normally, the key point is how to get the edit part control of the .Net
control genericly. Maybe we can determine the associated control type
one-by-one, then write separate code to get the edit control handle
one-by-one. Although not an elegent solution, but should can work.(it seems
that there is not many controls have edit control portion)

#2, .Net winform provided localization feature to resolve this problem. We
can first set Form.Localization property to true in propertybrowser, then
choose different language in the Language property. Then we can store
several versions of culture resource in the application resource file. At
runtime, winform will choose different resource based on the current
culture information. The below link contains several good articles
regarding .Net localization:
http://www.windowsforms.net/Articles...=Localization&
ModuleFilter=131&tabindex=3

Hope this helps

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Dec 30 '05 #6
Hi Graham,

Does my reply make sense to you? Is your problem resolved? If you still
have any concern, please feel free to tell me, thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Jan 4 '06 #7
Hi Graham,

Form your email, I see that you still have some concern regarding this
issue. Your concern comment listed below:

"I would be curious, however, if you knew where in the Win32 API I could
extract the labels used for the text box context menu ("Cut", "Copy",
etc.). (Without that, I can't internationalize my code --- but I can't find
it anywhere!)"

I am not sure what do you mean by "extracting the labels used for the text
box context menu", if you want to do globalization to your winform, I think
you should use the .Net Winform localization feature which I provided in
last reply. Does it meet your need? If you missed that point, I will
repaste it here:

#2, .Net winform provided localization feature to resolve this problem. We
can first set Form.Localization property to true in propertybrowser, then
choose different language in the Language property. Then we can store
several versions of culture resource in the application resource file. At
runtime, winform will choose different resource based on the current
culture information. The below link contains several good articles
regarding .Net localization:
http://www.windowsforms.net/Articles...=Localization&
ModuleFilter=131&tabindex=3

If I misunderstand your point, please feel free to show your real concern
to me, I will follow up with you. Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Jan 5 '06 #8
I don't want to internationalize a Winform -- I'm writing a replacement
ComboBox that extends the ComboBox's ContextMenu. (See my original
message.) Unfortunately, that ContextMenu is provided somewhere below
the CLR -- in the Win32 API, presumably, so that the labels on the
ContextMenu (Cut, Copy, etc.) aren't actually coming from any resource
file; they're coming from the localized version of Windows that the
user has installed. Which is fine, generally speaking, except when I
want to re-create that ContextMenu (Cut, Copy, etc.) but add things to
it. Is there an API call I can make to retrieve these labels? I'm
pretty sure we're talking lower than the CultureInfo class.

Jan 9 '06 #9
Hi Graham,

Thanks for your feedback.

No, the default contextmenu is not constituted by labels. It is just
resource for many Win32 controls, this resource is embeded in User32.dll,
you can open this user32.dll in System32 directory with VS.net and see the
contextmenu resource.

I am not sure why original suggestion of using a .Net context menu to
implement the default contextmenu function does not meet your need? Can you
show me your key concern to me? Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Jan 10 '06 #10
Sure, I'll clarify. Your original suggestion ("using a .Net context
menu to implement the default contextmenu function") works fine, it's
just not nearly as simple as you seemed to think it would be -- that's
why I had to write that longish replacement, as posted.

You'll remember, I wanted to add an item to the default ComboBox
ContextMenu. In other words, I wanted all the usual CTextBox menu items
and behaviors (Copy, Cut, Paste, Undo), as well as my own.
Unfortunately, if you set the ContextMenu property of a ComboBox, you
lose the default menu entirely. So I needed a way to replicate the
"normal" CTextBox context menu in a way that is extensible.

However, with my code, you'll get the English menu item labels ("Copy,
Cut") no matter what the user's copy of Windows would indicate. (In
France, the labels are in French.) So I thought I'd see if there was an
easy way to retrieve those labels from the Windows API. There doesn't
appear to be, as far as I can tell.

Yours,

Graham Charles

Jan 21 '06 #11
Hi Graham,

Thanks for your feedback.

The default contextmenu is the resource embeded in user32.dll, and the
common control does not expose a way to get this resource. I think we have
to re-implement the contextmenu to get the similiar function.

For the localization issue, just as I pointed in original reply, .Net
introduced Localization feature, which we can use to show different
language context menu. Thanks

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.

Jan 25 '06 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Peter Gorelczenko | last post by:
Good Morning, I'm running Alpha 4.1 on Linux. I'm new to MySql but familliar with othe= r=20 databases. I set up a user with "Create Temporary Tables" permissions. = That=20 user can create...
2
by: Heist | last post by:
Hi, I just want to know to turn this: CREATE TABLE . ( NOT NULL , (50) COLLATE French_CI_AS NULL , NOT NULL , (50) COLLATE French_CI_AS NOT NULL , NULL , NULL ) ON into this:
1
by: M A Srinivas | last post by:
I have the following requirement I am creating a login and database user 'test' on a database with dbo role . I want to remove create table , alter table permisions to this user. I am able to...
1
by: Bruce | last post by:
Hi, I want to change the datatype of an existing column from char to varbinary. When I run the "Alter Table" statement, I get the following error message - Disallowed implicit conversion...
2
by: Angelos | last post by:
Hello jsut a quick question... Is it possible to alter the DATABASE structure after it is CREATED AND POPULATED WITH RECORDS. For example RENAME fields, Change datatypes etc... If not what is the...
10
by: Jane | last post by:
Does any one know why this statement is failing? db2 => ALTER TABLE ELMT_T ALTER COLUMN CDTY_CD SET DATA TYPE VARCHAR(51) DB21034E The command was processed as an SQL statement because it was...
2
by: HjKlOp | last post by:
Can I set fields lenghts of an existing database with "ALTER TABLE" command without lost data ?
3
by: Jeff Kish | last post by:
Hi. I'm getting errors like this when I try to run an upgrade script I'm trying to write/test: altering labels to length 60 Server: Msg 5074, Level 16, State 4, Line 5 The object...
5
by: Giacomo | last post by:
Hi, I’ve the following error message: --------------- ALTER TABLE . ALTER COLUMN varchar(10) Go Server: messaggio 4929, livello 16, stato 1, riga 1
2
by: goyosito | last post by:
I'm working with DB2 ver. 8.x and I'm trying to change the precision of decimal(10) to decimal(20). My script is: ALTER TABLE xyz ALTER COLUMN campo SET DATA TYPE DECIMAL(20, 0); but I got...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.