VB.NET How to send key 46 (Chr(46)) with SendMessage - vb.net

I am Automating IBM iSeries Emulators using VB.net, created GUI that embeds the external iSeries Emulator Window in a WindowsForm Panel using the "SetParent" API .. To communicate with the iSeries Window I use the SendMessage API to send Key's to the Screen. I am aware of the sendkeys.keys in .net, but this way I dont have to SetForegroundWindow and reactivate my Form.
My program reads the output of a scale and validates if the received data is good, if so it will send the output to the iSeries Screen using this code (UserApi is my Lib):
For Each element As Char In CStr(txtto400.Text)
UserApi.SendMessage(as400WindowHandle, 256, CType(Convert.ToInt32(element), IntPtr), CType(0, IntPtr))
Next
I done this a few times on other projects and this method works good, but in my TextBox (txtto400.Text) my weight has a Value like "000.88 KG".
SendMessage will not send the key "46" which is a period (.) Instead it would be "00088 KG"
Does anyone have an idea why this dont work? Any suggestions what I could do?
EDIT:
Thanks to Paul B. which gave me the hint.
Here is how I resolved it.
My SendMessage function looks like this:
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
Public Shared Function SendMessage( _
ByVal hwnd As IntPtr, _
ByVal wMsg As UInt32, _
ByVal wParam As IntPtr, _
ByVal lParam As IntPtr) As IntPtr
End Function
I created a variable that holds the VK_OEM_PERIOD:
Public Const VK_OEM_PERIOD = &HBE
Created a Function that will check the Chr:
Public Function vk_key(key As Char) As Integer
Select Case key
Case Is = Chr(46)
Return VK_OEM_PERIOD
Case Else
Return AscW(key)
End Select
End Function
here is how I pass it to the iSeries Window:
For Each element As Char In txtto400.Text
UserApi.SendMessage(as400WindowHandle, 256, vk_key(element), 0)
Next

The WM_KEYDOWN message expects "The virtual-key code of the nonsystem key" as wParam (see MSDN).
This happens to correspond to the key character's ASCII value for alphanumeric signs but not for all other keys. For a period I think you need to send VK_OEM_PERIOD.
You can find the table of virtual-key codes here: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx

Related

How to click the enter button on the keyboard?

Is there a way to Click the ENTER key on the keyboard, other than SendKeys.Send("{ENTER}"?
I have an Application I created in VB.net that will create a line of text then send it to another application with AppActivate, it works great when the receiving application was created in C++. But when the receiving application was created in Java the SendKeys.Send("{ENTER}" will not work. All the text is transferred to the Java application but the ENTER button will not click.
Is there another way to Click ENTER on the Keyboard or simulate it?
Thank You
Have you tried P/Invoke?
For example:
<DllImport("user32.dll", SetLastError:=True, EntryPoint:="PostMessageA")>
Public Shared Function PostMessage(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Boolean
Public Const WM_KEYDOWN As Integer = &H0100 'Key Down Event
Public Const VK_RETURN As Integer = &H0D 'Enter Key
Public Shared Sub SendKeyDownEvent(ByVal hWnd As IntPtr, ByVal key As Integer)
PostMessage(hWnd, WM_KEYDOWN, key, 0)
System.Threading.Thread.Sleep(500)
End Sub
And you could call it like:
SendKeyDownEvent(handleToApplication, VK_RETURN)
There are plenty of resources available for obtaining handles to other applications:
https://www.codeproject.com/Tips/825946/Csharp-VB-NET-and-WinAPI-How-to-Access-Window-of-O
https://kellyschronicles.wordpress.com/2008/06/23/get-window-handles-associated-with-process-in-vb-net/

Is there something special about the wndProc messages for a RichEdit20WPT window?

I am currently trying to subclass an Edit Control, in particular the subject of en Email in the Outlook Client. This control is of class RichEdit20WPT.
I get a wndProc by using the following WINAPI methods.
<DllImport("ComCtl32.dll", CharSet:=CharSet.Auto)> _
Public Shared Function SetWindowSubclass(hWnd As IntPtr, newProc As Win32SubClassProc, uIdSubclass As IntPtr, dwRefData As IntPtr) As Integer
End Function
<DllImport("comctl32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function DefSubclassProc(ByVal hWnd As IntPtr, ByVal uMsg As IntPtr, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
Public Delegate Function Win32SubClassProc(hWnd As IntPtr, Msg As IntPtr, wParam As IntPtr, lParam As IntPtr, uIdSubclass As IntPtr, dwRefData As IntPtr) As Integer
And would then have a wndProc like this;
Private WM_CONTEXTMENU As IntPtr = &H7B
Private Function SubClassProc(hWnd As IntPtr, Msg As IntPtr, wParam As IntPtr, lParam As IntPtr, uIdSubclass As IntPtr, dwRefData As IntPtr) As Integer
Select Case Msg
Case WM_DESTROY
Case WM_NCDESTROY
Case WM_LBUTTONDOWN
Case WM_CONTEXTMENU 'NEVER HAPPENS
Case WM_RBUTTONDOWN
End Select
Return DefSubclassProc(hWnd, Msg, wParam, lParam)
End Function
I get the L and R button down and up messages but no WM_CONTEXTMENU. My current intention is to add a menu item to the context menu so as an alternative I am using the WM_RBUTTONDOWN message.
Is this control special and known to not show the WM_CONTEXTMENU message?
I also have a challenge to find the messages that occur after choosing something on the context menu. My understanding is that the messages of the menu item clicked in the context menu are given to the parent which in this case is this RichEdit20WPT window. Is this correct? Note I am not making my own context menu I am appending to the existing one so I am not changing the owner of the context menu or anything like that.
Thank you to all the comments which helped me to at least keep searching for answers or in this case messages. For anyone coming here and wanting to add to the context menu of an Outlook Menu.
First here are two good links which explain generally what to do.
How to disable copy/paste commands in the Windows edit control context menu?
Modify right-click context menu in standard controls
Anyone reading them can assume for a standard edit control such as a text box on a windows form application that the messages will be sent.
For Outlook (At least 2007 / 2010) this is what I have found;
The text box you need to find for both an Explorer and Inspector is RichEdit20WPT
This window however does not get two of the key messages required. (a) it does not get WM_INITMENUPOPUP to know before the context menu is being shown and secondly (b) it does not get a message when you choose something in the context menu which is a WM_COMMAND in this case.
Inorder to amend the context menu you need to subclass the subject text box's parent which is a window of class #32770.
As the parent is subclassed there are a few challenges. To know when our target text box as had a right click from the #32770 window you need to look for the WM_SETCURSOR.
Something like this where the wParam will be the text box's Hwnd and the HiWord will be the mouse message;
Case NativeMethodsEX.WM_SETCURSOR
If wParam = subjectHwnd Then
Dim pMap As New NativeMethodsEX.LParamMap(lParam)
If pMap.hiword = NativeMethodsEX.WM_RBUTTONUP Then
rightClickOnSubject = True
Else
rightClickOnSubject = False
End If
End If
Then shortly after there will be this message
Case NativeMethodsEX.WM_INITMENUPOPUP
If rightClickOnSubject Then
'check here if you want to display something.
End If
Once you know this, you can implement the ideas from the other forum answers.

Vb.net: Send text to window via windows messages

I'm trying to make a program with vb.net (VS2008) for studio shooting with my Nikon D600.
I'm using a program called ControlMyNikon for tethered shooting and it's working perfectly.
It has this external control-feature with following instructions: http://i.jjj.fi/a9dAQ7z.png
Could someone give me hint what does 'send string to 'ControlMyNikon v4.1' window with windows messages' actually mean?
I tried with SendMessages.
I was able to change window title with WM_SETTEXT but that's all.
I'm able to get the window handle but don't know how to send any string to it.
Help? :)
Ugh, Nikon is pretty infamous for writing truly crappy shovelware. This does not disappoint. Here are some declarations that ought to work. Try the Unicode version first. If that produces Chinese text then use the Ansi version:
Imports System.Runtime.InteropServices
Class NativeMethods
Friend Const WM_SETTEXT As Integer = 12
<DllImport("user32.dll", EntryPoint:="SendMessageW", CharSet:=CharSet.Unicode)> _
Friend Shared Function SetWindowTextUnicode(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="SendMessageA", CharSet:=CharSet.Ansi)> _
Friend Shared Function SetWindowTextAnsi(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
End Function
End Class
Usage:
NativeMethods.SetWindowTextUnicode(handleYouFound, WM_SETTTEXT, IntPtr.Zero, "shoot")
If neither works then you are probably using the wrong window handle. Use Spy++ to double check that you located the window properly.

How do I read cells of another program's TStringGrid control?

How can I extract items from other application's gridview? The class name of the control is TStringGrid.
I can get the handle of the TStringGrid window with FindWindowEx using these declarations:
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
<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
code:
Dim TheMainForm As Integer = FindWindow("form", "fname")
Dim GV As Integer = FindWindowEx(TheMainForm, 0, "TStringGrid", "")
How can I extract the items from GV (TStringGrid handle)?
(I have to finish this project by tomorrow.)
A Delphi string grid is not a windows control. It's a custom Delphi control. As such it doesn't respond to windows messages asking for its content. Without the source of the app you would need to reverse engineer the app to work out where the content is stored.
Realistically the most effective way to do this will be to inject a thread into the target application. That thread can then do the work of reading the information and can then use some IPC to get the data back to your VB process.
In order to do this you will, ideally, need:
Knowledge of the exact version of Delphi used to build the app.
A deep understanding of the Delphi compiler and RTL.
The Delphi VCL source code for TStringGrid.
I've no idea how you'll be able to synchronize your reading thread with the Delphi app.
Anyway, whilst what you ask for is, in theory possible, in reality it is completely impractical. The sensible solution is to ask the authors of the Delphi program to provide an automation interface.

VB.net sendmessge to console box

Hey all, i am trying to send some text to a console box (dos box) from my vb program but i can not seem to get it working.
Here is my current code:
Dim blah As Long
Private Const WM_GETTEXT As Integer = &HD
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
blah = FindWindow1(vbNullString, "Form1")
blah = FindWindowEx(blah, vbNullString, "ConsoleWindowClass", vbNullString)
Debug.Print(blah)
SendMessage(blah, WM_SETTEXT, 200, "A")
Though that does work, it only puts a A for the title bar and not within the console.
Any help would be great! :o)
David
I've not tried it but I think you might want to look at AttachConsole to attach your process to the console of the command line process. Then you should be able to use the Console.WriteLine and similar methods I'd assume.
You can find a sample (in C#, but should be easy to convert to VB using one of the online converters) on the PInvoke page.