I found this code around the net but I don't know how to use it. I just want to build a code that will execute if a desired window is active.
This is for API as i read about my research,
<DllImport("USER32.DLL", EntryPoint:="GetActiveWindow", SetLastError:=True,
CharSet:=CharSet.Unicode, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)>
Public Shared Function GetActiveWindowHandle() As System.IntPtr
End Function
<DllImport("USER32.DLL", EntryPoint:="GetWindowText", SetLastError:=True,
CharSet:=CharSet.Unicode, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)>
Public Shared Function GetActiveWindowText(ByVal hWnd As System.IntPtr, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer
End Function
He used this to get the text,
Dim caption As New System.Text.StringBuilder(256)
Dim hWnd As IntPtr = GetActiveWindowHandle()
GetActiveWindowText(hWnd, caption, caption.Capacity)
MsgBox(caption.ToString)
I put that code in the form_load() but it doesn't display anything. Like nothing happens. Where should I put it or how to make it work. I want to get the window title and put it in an If statement. I also found some programmers that used this code:
Dim hWnd As IntPtr = GetForegroundWindow()
I just want to determine the window on focus, get the text and put it in an If statement. Can you please simplify this code more. What is the difference of a FOCUS window and ACTIVE window? i guess ACTIVE are the open windows but FOCUS is the only one that the user is using. I want to know the title of the FOCUS one.
For example,
If "title of the window on focus" = "notepad" Then
MsgBox("notepad")
Else
MsgBox("not notepad")
End If
And where there is 2 windows open, if the notepad is focused it will display the notepad on message box and when the user change its focus to the other window the message box will automatically display the not notepad message.
Related
I have a query, how can I kill a process with just the class name using FindWindowEx
If you have been able to reliably get a window handle back from calling FindWindowEx you can then use GetWindowThreadProcessId to find the ID of the process from the window handle.
Once you have the process ID you can find the Process by that ID and call Kill() on it. For example:
Imports System.Runtime.InteropServices
Imports System.Diagnostics
Module Module1
<DllImport("user32.dll", SetLastError:=True)>
Private Function GetWindowThreadProcessId(ByVal hwnd As IntPtr,
ByRef lpdwProcessId As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Function FindWindowEx(ByVal parentHandle As IntPtr,
ByVal childAfter As IntPtr,
ByVal lclassName As String,
ByVal windowTitle As String) As IntPtr
End Function
Sub Main()
Dim hWnd As IntPtr = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Chrome_WidgetWin_0", "Spotify Premium")
Dim ProcessId As Integer
GetWindowThreadProcessId(hWnd, ProcessId)
If ProcessId <> 0 Then
Dim Process As Process = Process.GetProcessById(ProcessId)
Process.Kill()
End If
End Sub
End Module
The tricky part will be making sure that you can always get a window handle. Think about cases when there are multiple instances of the handle. You mention class name but it will likely also be necessary to supply the window title to FindWindowEx.
You may also need to consider what happens if calling Process.Kill() should throw an exception, for example, if the user that your program is running under doesn't have the rights to kill that particular process.
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.
I have a web app that successfully gets to a page and clicks an "Upload File" button.
My app also successfully handles pop-up windows by monitoring and hooking them. For the most part, it's just to click "OK" or "Cancel" buttons. Buttons are easy.
What I need help with is the Choose-File dialog. I'm hooking it fine, but there are a lot of controls on it and I need some direction.
These are the child controls on it:
DUIViewWndClassName,DirectUIHWND,CtrlNotifySink,NamespaceTreeControl,Static,SysTreeView32,CtrlNotifySink,Shell Preview Extension Host,CtrlNotifySink,SHELLDLL_DefView,DirectUIHWND,CtrlNotifySink,ScrollBar,CtrlNotifySink,ScrollBar,Static,Static,Static,ListBox,Static,Static,ComboBoxEx32,ComboBox,Edit,Static,ComboBox,Button,Button,Button,ScrollBar,WorkerW,ReBarWindow32,TravelBand,ToolbarWindow32,Address Band Root,msctls_progress32,Breadcrumb Parent,ToolbarWindow32,ToolbarWindow32,UniversalSearchBand,Search Box,SearchEditBoxWrapperClass,DirectUIHWND
I would be happy with sticking an exact path/file into the File-Name textbox/combobox and clicking "Open". The button part is easy, but I don't know either how to select files in the window, and/or how to put my path into the File-Name entry field.
Right now I have something like this:
<DllImport("user32.dll")> _
Private Shared Function GetClassName(ByVal hWnd As IntPtr, ByVal lpClassName As StringBuilder, ByVal nMaxCount As Int32) As Int32
End Function
<DllImport("user32.dll")> _
Private Shared Function GetWindowText(ByVal hWnd As IntPtr, ByVal text As StringBuilder, ByVal maxLength As Int32) As Int32
End Function
<DllImport("user32.dll")> _
Private Shared Function GetDlgCtrlID(ByVal hwndCtl As IntPtr) As Integer
End Function
....
Private Shared Function hwndHandler() As Int32
Dim ptrButtonhwnd As IntPtr
For Each pChild As IntPtr In Interop.ChildWindows(pPopup.hwnd)
Dim sbControl As New StringBuilder(255)
GetClassName(pChild, sbControl, sbControl.Capacity)
If "Button".Equals(sbControl.ToString()) Then
Dim sbText As New StringBuilder(255)
GetWindowText(pChildOfDialog, sbText, sbText.Capacity)
If "&Open".Equals(sbText.ToString()) Then
ptrButtonHwnd = pChild
End If
End If
Next
If ptrButtonHwnd <> IntPtr.Zero Then
Dim ctrlId As Int32 = GetDlgCtrlID(ptrButtonHwnd)
SendMessage(pPopup.hwnd, WM_COMMAND, New IntPtr(ctrlId), ptrButtonHwnd)
Return 1
End If
Return 0
End Function
This works fine, but I need to add something to select a file to open either by inputting it into the text/combo field, or by selecting it in the window.
I found the answer was to look for a control with the text of "Edit", which was one of the controls listed in my original list.
So according to my code posted above, I made a new pointer ptrEdit, and assigned it the control where "Edit".Equals(sbControl.ToString()).
Then to manipulate it, I used one of the DLLs:
If ptrEdit <> IntPtr.Zero Then
SetWindowText(pEditHwnd, strFilePath)
If ptrButtonHwnd <> IntPtr.Zero Then
Dim ctrlId As Int32 = GetDlgCtrlID(ptrButtonHwnd)
SendMessage(cwp.hwnd, WM_COMMAND, New IntPtr(ctrlId), ptrButtonHwnd)
Return 1
End If
End If
And so I was able to control the "Choose File To Upload" Dialog Box.
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.
My question maybe not be very clear, but I just want to know how this process is called or references needed to create something similar, so I can investigate on my own ( but if you have code is welcome.. LOL...)
Basically I have 2 desktop programs ( A and B). For A, I do not have the source code, for B I do. What I need is to create some service/program that after a screen pops up from program A, automatically runs B. IN other words, capture the moment a specific screen is shown in A and execute B.
My real life scenario is that I have a very basic POS where I can't collect customer demographics ( zip code, etc), so I created a second application to capture that but my cashiers are always forgetting to run the program and I need to find a way to run it after a screen is shown ( let's say the "Change Due" in the POS, so they don't forget to run it.
Any pointings will be appreciated!
Thanks
So here's a very quick example of how you can do this with VB which should be very easy to convert to C# if needed. The code search visible windows by title. If your open window doesn't have a title you'll have to work a little more. You can probably find the title of your main app and just enumerate its child windows.
First, some unmanaged code to talk to Win32 directly:
Option Strict On
Option Explicit On
Imports System.Runtime.InteropServices
Imports System.Text
Public Class Unmanaged
<DllImport("user32.dll")>
Public Shared Function EnumWindows(ByVal lpEnumFunc As CallBack, ByVal lParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", SetLastError:=True)>
Public Shared Function GetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Public Shared Function IsWindowVisible(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Public Const SW_SHOW = 5
Public Const SW_RESTORE = 9
Public Const GW_OWNER = 4
Public Const GWL_HWNDPARENT = (-8)
Public Const GWL_EXSTYLE = (-20)
Public Const WS_EX_TOOLWINDOW = &H80
Public Const WS_EX_APPWINDOW = &H40000
Public Delegate Function CallBack(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
End Class
Then a non-GUI module which should be set as the startup object:
Option Explicit On
Option Strict On
Module Module1
''//Code loosely base on http://msdntracker.blogspot.com/2008/03/list-currently-opened-windows-with.html
''//This is the title of the window that we are looking for
Public ReadOnly WatchForTitle As String = "About Mozilla Firefox"
''//This is the form that we will show when we find the above
Private MainForm As Form1
<STAThread()>
Public Sub Main()
''//Create the form but don not show it
MainForm = New Form1()
''//Create an infinite loop that checks to see if the target window is open and sleeps for a bit between checks
Do While True
Unmanaged.EnumWindows(AddressOf fEnumWindowsCallBack, IntPtr.Zero)
''//Sleep for a bit
System.Threading.Thread.Sleep(500)
Loop
End Sub
Private Function fEnumWindowsCallBack(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
''//Ignore our own handle
If hwnd <> Form1.Handle Then
''//Make sure its visible
If Unmanaged.IsWindowVisible(hwnd) Then
Dim lExStyle = Unmanaged.GetWindowLong(hwnd, Unmanaged.GWL_EXSTYLE)
''//We probably want to ignore tool windows, but remove this if needed
If (((lExStyle And Unmanaged.WS_EX_TOOLWINDOW) = 0)) Then
''//Create a buffer to store the title of the window
Dim sWindowText As New System.Text.StringBuilder(256)
''//Get the title of the window
Dim lReturn = Unmanaged.GetWindowText(hwnd, sWindowText, sWindowText.Length - 1)
''//When you are looking for window title uncomment this line
'Trace.WriteLine(sWindowText)
''//Sanity check, make sure we found a window title
If lReturn <> 0 Then
''//See if it matches what we are looking for
If sWindowText.ToString() = WatchForTitle Then
''//If so, show our form
Form1.ShowDialog()
End If
End If
End If
End If
End If
fEnumWindowsCallBack = True
End Function
End Module
Lastly create a regular Windows Form called Form1 (or whatever you want, you'll just need to change it in the Module above).
If you test this it will pop open the form if you go to Firefox's Help->About menu.
I should point out, this is just a start. You'll want to perform better error checking and handle when the program closes or exists or whatever.
It's very unlikely that there is any 'good' way to interact with program A. There won't be a traditional 'event' that fires or anything like that.
Your best bet is going to be looking at some WIN32 API calls. For example, you can use GetPixel() to return the color at a specific location on the screen. So, if program A displays a particular image or screen that is measurably different from any other screen, you can write code that monitors the screen and checks for a match. When the match is found you can execute any code you want, including launching B.