|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
alter built-in ContextMenuentry 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(_RemoveMRUItemMenu) 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. 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. 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 (gra***@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 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/default.aspx?PageID=1&Cat=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. 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. 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. 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 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.
Microsoft doesn't want you to use VB .Net
Unmanaged C dll call The connection is dead XML question WIA.ImageFile to System.Drawing.Image How to loop thru each controls ? Using VB Keywords In An Enum Statement Developing Application like Photoshop Serializing / persistently storing & retrieving VB objects in & from SQL Server not all paths return a value |
|||||||||||||||||||||||