How to capture mouse right click paste function in Winforms - vb.net

I would like to know how to capture right click and paste option through mouse click.
It is a winforms application. I would be modifying the contents of clipboard before pasting.
I am able to perform this through ctrl+V but not able to find a way to handle mouse right click.
I have tried this so far:
Private Const WM_PASTE As Integer = &H302
Protected Overrides Sub WndProc(ByRef msg As Message)
If msg.Msg = WM_PASTE AndAlso Clipboard.ContainsText() Then
Clipboard.SetText(Clipboard.GetText().Replace(vbCrLf, " "))
End If
MyBase.WndProc(msg)
End Sub

You have to process the WM_PASTE windows message using WndProc (a list of all messages can be found here).
For example, this TextBox will print all text pasted into it (no matter how) to the console instead of displaying it itself:
Class CapturePasteBox
Inherits TextBox
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = &H302 AndAlso Clipboard.ContainsText() Then
Dim text = Clipboard.GetText()
'' do something with text
Console.WriteLine(text)
Return '' return so the text won't be pasted into the TextBox
End If
MyBase.WndProc(m)
End Sub
End Class
In response to your comment:
The ComboBox-control needs some special treatment, since
When sent to a combo box, the WM_PASTE message is handled by its edit control.
So you can use the following function/class using a NativeWindow:
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError := True)> _
Private Shared Function FindWindowEx(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
End Function
Public Class PasteHandler
Inherits NativeWindow
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = &H302 Then
Clipboard.SetText(ClipBoard.GetText().Replace("e", "XXX"))
End If
MyBase.WndProc(m)
End Sub
End Class
and use it with your ComboBox:
'' Get the edit control of the combobox
Dim lhWnd As IntPtr = FindWindowEx(yourComboBox.Handle, IntPtr.Zero, "EDIT", Nothing)
'' assign the edit control to the Pastehandler
Dim p As New PasteHandler()
p.AssignHandle(lhWnd)

I found this to be working like awesome:
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function FindWindowEx(hwndParent As IntPtr, hwndChildAfter As IntPtr, lpszClass As String, lpszWindow As String) As IntPtr
End Function
Private Sub SearchCriteria_MouseDown(sender As Object, e As MouseEventArgs) Handles SearchCriteria.MouseDown
Dim lhWnd As IntPtr = FindWindowEx(SearchCriteria.Handle, IntPtr.Zero, "EDIT", Nothing)
If e.Button = Windows.Forms.MouseButtons.Right And lhWnd <> 0 Then
Clipboard.SetText(Clipboard.GetText().Replace(vbCrLf, " "))
End If
End Sub

Related

Get the highlighted text from outside of form in vb.net

I want to copy the highlighted text from outside of winform using vb.net.
For example, if the user highlights a text in a browser or in notepad it should be copied into a textbox in a winform.
Any help would be great!
Thanks in advance.
Ok!
Thanks to this link I got my answer.
My Logic is First of all the user will highlight a value, not specific to browser but anywhere.
then the user will press the Hotkey, In my case it's F8. Then Code will trigger the copy command and then retrieve the Clipboard value and will assign it to a textbox text.
Here is the Full Code along with Helping Class.
Hotkey.vb
Public Class Hotkey
#Region "Declarations - WinAPI, Hotkey constant and Modifier Enum"
''' <summary>
''' Declaration of winAPI function wrappers. The winAPI functions are used to register / unregister a hotkey
''' </summary>
Private Declare Function RegisterHotKey Lib "user32" _
(ByVal hwnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Integer
Private Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As IntPtr, ByVal id As Integer) As Integer
Public Const WM_HOTKEY As Integer = &H312
Enum KeyModifier
None = 0
Alt = &H1
Control = &H2
Shift = &H4
Winkey = &H8
End Enum 'This enum is just to make it easier to call the registerHotKey function: The modifier integer codes are replaced by a friendly "Alt","Shift" etc.
#End Region
#Region "Hotkey registration, unregistration and handling"
Public Shared Sub registerHotkey(ByRef sourceForm As Form, ByVal triggerKey As String, ByVal modifier As KeyModifier)
RegisterHotKey(sourceForm.Handle, 1, modifier, &H77)
End Sub
Public Shared Sub unregisterHotkeys(ByRef sourceForm As Form)
UnregisterHotKey(sourceForm.Handle, 1) 'Remember to call unregisterHotkeys() when closing your application.
End Sub
Public Shared Sub handleHotKeyEvent(ByVal hotkeyID As IntPtr)
SendKeys.Send("^(c)") 'for Ctrl-C[/CODE]
End Sub
#End Region
End Class
This Section will Trigger the Hotkey Code and do the rest of logic
Main Form
'This Program will wait for a key to press in our case it will wait for the F8 key to be press
'Then it will copy the highlighted text (Outside and Inside of the form) and will concatinate the text with a webaddress'
Imports Name_Of_Your_Project.Hotkey
Public Class Form1
'This Chunk of code will register the F8 key as a main key for the Program'
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Hotkey.registerHotkey(Me, "f8", Hotkey.KeyModifier.None)
End Sub
'This sub will trigger the Hotkey Sub Code in the Hotkey.vb Class'
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = Hotkey.WM_HOTKEY Then
Hotkey.handleHotKeyEvent(m.WParam)
'After pressing the F8 key It will copy the highlighted data from anywhere and store it to the clipboard'
If Clipboard.ContainsText Then
Try
Textbox1.text = My.Computer.Clipboard.GetData(DataFormats.Text).ToString
Catch ex As Exception
MessageBox.Show("Error in Program" + ex.ToString())
End Try
End If
End If
MyBase.WndProc(m)
End Sub
'System wide hotkey event handling
End Class

Equivalent of ReisizeEnd event User Control

I have made a custom task pane using a user control.
Every time I resize it I raise a method called SuspendDrawing the reason I do this is because the buttons on my custom task pane flicker when I resize it therefore I need to suspend it. I add these buttons using the designer
This works like a treat but then I need to call a method called ResumeDrawing when the user stops resizing however I don't know what event I should use to call the ResumeDrawing method as there is no ResizeEnd event for a user control.
Any suggestions would be appreciated as I'm out of ideas.
My code is as follows
Public Property Resizing As Boolean
<DllImport("user32.dll", EntryPoint:="SendMessageA", ExactSpelling:=True, CharSet:=CharSet.Ansi, SetLastError:=True)>
Private Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function
Public Shared Sub SuspendDrawing(ByVal target As Control)
SendMessage(target.Handle, WM_SETREDRAW, 0, 0)
End Sub
Public Shared Sub ResumeDrawing(ByVal target As Control)
ResumeDrawing(target, True)
End Sub
Public Shared Sub ResumeDrawing(ByVal target As Control, ByVal redraw As Boolean)
SendMessage(target.Handle, WM_SETREDRAW, 1, 0)
If redraw Then
target.Refresh()
End If
End Sub
Private Sub SideBarPowerPoint_Resize(sender As Object, e As EventArgs) Handles MyBase.Resize
SuspendDrawing(Me)
End Sub
My Custom Task Pane
Dim taskPaneView = New PowerPointCommon.SideBarPowerPoint
sideBarTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(taskPaneView, " ")
If sideBarTaskPane.Visible = True Then
sideBarTaskPane.Visible = False
End If
sideBarTaskPane.Visible = True
sideBarTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight
sideBarTaskPane.Width = 100

VB .NET Outlook 2016 Add-in Subject Line

I am writing an add-in for Outlook 2016 using Visual Studio 2015. I added a button to the built-in New Mail tab. When clicked it adds the word "unencrypt" to the end of the subject line and then sends the email.
This works fine as long as the user has tabbed out of the subject line field after entering the subject. But if you type in the subject and then immediately click the button it wipes out the subject line and replaces it with "unencrypt".
However, when I step through in debug it works fine - it keeps the existing text even if I haven't tabbed out of the subject line. I figured there was some sort of delay in updating the Subject property of the mail item, but I manually put in a delay of 20 seconds and it still wiped out the subject line if I wasn't stepping through in debug.
I'm at a loss here. Is there a way to check the subject line textbox itself? or some other way to grab the text even if the user hasn't tabbed out?
Any help would be appreciated!
Private Sub Button1_Click(sender As Object, e As RibbonControlEventArgs) Handles Button1.Click
' Get the Application object
Dim application As Outlook.Application = Globals.ThisAddIn.Application
' Get the active Inspector object and check if is type of MailItem
Dim inspector As Outlook.Inspector = application.ActiveInspector()
Dim mailItem As Outlook.MailItem = TryCast(inspector.CurrentItem, Outlook.MailItem)
If mailItem IsNot Nothing Then
If mailItem.EntryID Is Nothing Then
If Not IsNothing(mailItem.Subject) AndAlso ((mailItem.Subject.Contains(" unencrypt")) OrElse (mailItem.Subject.Contains("unencrypt "))) Then
mailItem.Subject = mailItem.Subject
'ElseIf IsNothing(mailItem.Subject) Then
'System.Threading.Thread.Sleep(20000)
'mailItem.Subject = mailItem.Subject + " unencrypt"
Else
mailItem.Subject = mailItem.Subject + " unencrypt"
End If
If Not IsNothing(mailItem.To) AndAlso mailItem.To.ToString().Trim <> "" Then
mailItem.Send()
Else
MessageBox.Show("We need to know who to send this to. Make sure you enter at least one name.", "Microsoft Outlook", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1)
End If
End If
End If
End Sub
Edit:
Dmitry's answer got me where I needed, but for anyone else not familiar with the Windows API I added the code below and then simply called the GetSubject function from my original code instead of using the mailItem.Subject property.
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindowEx(ByVal parentHandle As IntPtr, _
ByVal childAfter As IntPtr, _
ByVal lclassName As String, _
ByVal windowTitle As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow(ByVal lclassName As String, _
ByVal lWindowName As String) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetWindowText(ByVal hWnd As IntPtr, _
ByVal lpString As StringBuilder, _
ByVal nMaxCount As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As Integer
End Function
Private Function GetSubject(inspector As Outlook.Inspector) As String
Try
Dim inspectorHandle As IntPtr = FindWindow("rctrl_renwnd32", inspector.Caption)
Dim windowLevel2Handle As IntPtr = FindWindowEx(inspectorHandle, IntPtr.Zero, "AfxWndW", "")
Dim windowLevel3Handle As IntPtr = FindWindowEx(windowLevel2Handle, IntPtr.Zero, "AfxWndW", "")
Dim windowLevel4Handle As IntPtr = FindWindowEx(windowLevel3Handle, IntPtr.Zero, "#32770", "")
Dim SubjectHandle As IntPtr = FindWindowEx(windowLevel4Handle, IntPtr.Zero, "Static", "S&ubject")
Dim SubjectTextBoxHandle As IntPtr = FindWindowEx(windowLevel4Handle, SubjectHandle, "RichEdit20WPT", "")
Dim length As Integer = GetWindowTextLength(SubjectTextBoxHandle)
Dim sb As New StringBuilder(length + 1)
GetWindowText(SubjectTextBoxHandle, sb, sb.Capacity)
Return sb.ToString()
Catch
Return ""
End Try
End Function
The important part is that the subject edit box needs to lose focus for the OOM to become aware of the change.
You can use accessibility API or raw Windows API to access the contents of the edit box or you can try to focus some other inspector control, such as the message body editor.

How to add more items to the window context menu

I'm making an app for the company I work for and I was wondering how to customise the window's context menu like PuTTY's (aka, it has "New Session..." etc.). I've looked all over Google and can't find the answer I'm looking for.
make a new module and add Imports System.Runtime.InteropServices on top
then declare this
<Flags()> _
Public Enum MenuFlags As Integer
MF_BYPOSITION = 1024
MF_REMOVE = 4096
MF_SEPARATOR = 2048
MF_STRING = 0
End Enum
<DllImport("user32.dll", CallingConvention:=CallingConvention.Cdecl)> _
Public Function GetSystemMenu(ByVal hWnd As IntPtr, Optional ByVal bRevert As Boolean = False) As IntPtr
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Public Function AppendMenu(ByVal hMenu As IntPtr, ByVal uFlags As MenuFlags, ByVal uIDNewItem As Int32, ByVal lpNewItem As String) As Boolean
End Function
then on your form load handler add this code
Dim sysmenu As IntPtr = GetSystemMenu(Me.Handle)
AppendMenu(sysmenu, MenuFlags.MF_STRING, &H1FFF, "Hello")
then, in order to be able to capture the user click on your new menu item, you have to implement this function which will capture all messages, just add it to your form code
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_SYSCOMMAND Then
If m.WParam.ToInt32 = &H1FFF Then
' your menu item is clicked, call a function here
End If
End If
MyBase.WndProc(m)
End Sub

Detect Clipboard text change with unicode support in vb.net

iam using the below code to check text change in clipboard but its not supported with unicode chracters like ا ب ج is there any way to add support for unicode text or is there any other way to do same work?
#Region " Definitions "
'Constants for API Calls...
Private Const WM_DRAWCLIPBOARD As Integer = &H308
Private Const WM_CHANGECBCHAIN As Integer = &H30D
'Handle for next clipboard viewer...
Private mNextClipBoardViewerHWnd As IntPtr
'API declarations...
Declare Auto Function SetClipboardViewer Lib "user32" (ByVal HWnd As IntPtr) As IntPtr
Declare Auto Function ChangeClipboardChain Lib "user32" (ByVal HWnd As IntPtr, ByVal HWndNext As IntPtr) As Boolean
Declare Auto Function SendMessage Lib "User32" (ByVal HWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Long
#End Region
#Region " Contructor "
#End Region
#Region " Message Process "
'Override WndProc to get messages...
Protected Overrides Sub WndProc(ByRef m As Message)
Dim iData As IDataObject = New DataObject()
iData = Clipboard.GetDataObject()
Select Case m.Msg
Case Is = WM_DRAWCLIPBOARD 'The clipboard has changed...
'##########################################################################
' Process Clipboard Here :)........................
'##########################################################################
MsgBox(CStr(iData.GetData(DataFormats.Text)))
SendMessage(mNextClipBoardViewerHWnd, m.Msg, m.WParam, m.LParam)
Case Is = WM_CHANGECBCHAIN 'Another clipboard viewer has removed itself...
If m.WParam = CType(mNextClipBoardViewerHWnd, IntPtr) Then
mNextClipBoardViewerHWnd = m.LParam
Else
SendMessage(mNextClipBoardViewerHWnd, m.Msg, m.WParam, m.LParam)
End If
End Select
MyBase.WndProc(m)
End Sub
#End Region
#Region " Dispose "
'Form overrides dispose to clean up...
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
'Set the next clipboard viewer back to the original...
ChangeClipboardChain(Me.Handle, mNextClipBoardViewerHWnd)
MyBase.Dispose(disposing)
End If
End Sub
Your code is not able to detect changes for Unicode text because it is not looking for the Unicode text format. Ansi and Unicode use different clipboard formats, and they can coexist on the clipboard at the same time. DataFormats.Text only supports Ansi text. The documentation even says as much:
Specifies the standard ANSI text format
You need to look for DataFormats.UnicodeText instead of, or in addition to, DataFormats.Text, eg:
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
Case Is = WM_DRAWCLIPBOARD 'The clipboard has changed...
'##########################################################################
' Process Clipboard Here :)........................
'##########################################################################
Dim iData As IDataObject = Clipboard.GetDataObject()
Dim oData as Object = iData.GetData(DataFormats.Text)
If oData IsNot Nothing
MsgBox(CStr(oData), MsgBoxStyle.OKOnly, "Ansi")
End If
oData = iData.GetData(DataFormats.UnicodeText)
If oData IsNot Nothing
MsgBox(CStr(oData), MsgBoxStyle.OKOnly, "Unicode")
End If
Case Is = WM_CHANGECBCHAIN 'Another clipboard viewer has removed itself...
If m.WParam = CType(mNextClipBoardViewerHWnd, IntPtr) Then
mNextClipBoardViewerHWnd = m.LParam
Else
SendMessage(mNextClipBoardViewerHWnd, m.Msg, m.WParam, m.LParam)
End If
End Select
MyBase.WndProc(m)
End Sub