I can't figure out how to make my ComboBox (which lists all open windows(I can see these already)) to make my form type on that selected window. I just can't make it so when screen1 is selected, it clicks on that screen.
Example:
I have 2 different forms open.
Form (1) clicks on a specified screen. (screen1)
Form (2) clicks on a different specified screen. (screen2)
The forms are the same program just opened twice.
I want my form to be able to click on a certain screen even if it's not open.
Imports System.Runtime.InteropServices
Imports System.Diagnostics
Public Class W1
Public Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As Int32) As Int32
Public Declare Function IsWindowVisible Lib "user32.dll" (ByVal hwnd As IntPtr) As Boolean
Public Delegate Function EnumWindowsProc(ByVal hwnd As IntPtr, ByVal lParam As Int32) As Boolean
Public Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hwnd As IntPtr, ByVal lpString As String, ByVal cch As Int32) As Int32
Public Declare Function GetWindowTextLength Lib "user32.dll" Alias "GetWindowTextLengthA" (ByVal hwnd As IntPtr) As Int32
Public Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hwnd As IntPtr, ByVal nIndex As Int32) As Int32
Public Declare Function GetParent Lib "user32.dll" (ByVal intptr As IntPtr) As IntPtr
Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
Public Property SelectedItem As Object
Public Const GWL_HWNDPARENT As Int32 = -8
Private newwindowlist As List(Of String)
Private newhandlelist As List(Of IntPtr)
Private Structure RECT
Public left As Integer
Public top As Integer
Public right As Integer
Public bottom As Integer
Public Sub New(ByVal _left As Integer, ByVal _top As Integer, ByVal _right As Integer, ByVal _bottom As Integer)
left = _left
top = _top
right = _right
bottom = _bottom
End Sub
End Structure
Private Function EnumWinProc(ByVal hwnd As IntPtr, ByVal lParam As Int32) As Boolean
If IsWindowVisible(hwnd) Then
If GetParent(hwnd) = IntPtr.Zero Then
If GetWindowLong(hwnd, GWL_HWNDPARENT) = 0 Then
Dim str As String = String.Empty.PadLeft(GetWindowTextLength(hwnd) + 1)
GetWindowText(hwnd, str, str.Length)
If Not String.IsNullOrEmpty(str.Substring(0, str.Length - 1)) Then
newwindowlist.Add(str.Substring(0, str.Length - 1))
End If
End If
End If
End If
EnumWinProc = True
End Function
Private Sub RefreshWindowList()
newwindowlist = New List(Of String)
EnumWindows(AddressOf EnumWinProc, CInt(True))
End Sub
And
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
RefreshWindowList()
For Each item As String In newwindowlist
ComboBox1.Items.Add(item)
ComboBox1.SelectedItem = Convert.ToInt64(GWL_HWNDPARENT)
Next
End Sub
Related
The Goal:
I am trying to create a Visual Basic program that will execute some code whenever any new program window is displayed on screen. Just for an easy to understand example: When I launch a program like File Explorer, I want a message box to be displayed when the window for File Explorer is displayed on screen.
The Problem:
Using the code I provided below, my desired outcome works correctly. However, it will also display a message box whenever something like a context menu is displayed as well. I do not want this. I only want a message box to be displayed whenever an actual program window is displayed. I've tried adding checks for checking if the window has 'minimize', 'maximize', and 'close' buttons. But after adding those checks, a message box no longer gets displayed at all, even with a window that has caption buttons, like File Explorer.
This is my code:
Private Declare Function GetForegroundWindow Lib "user32.dll" () As IntPtr
Declare Auto Function SetWinEventHook Lib "user32.dll" (ByVal eventMin As Integer, ByVal eventMax As Integer, ByVal hmodWinEventProc As IntPtr, ByVal lpfnWinEventProc As WinEventDelegate, ByVal idProcess As Integer, ByVal idThread As Integer, ByVal dwflags As Integer) As IntPtr
Declare Auto Function UnhookWinEvent Lib "user32.dll" (ByVal hWinEventHook As IntPtr) As Boolean
Delegate Sub WinEventDelegate(ByVal hWinEventHook As IntPtr, ByVal eventType As Integer, ByVal hwnd As IntPtr, ByVal idObject As Integer, ByVal idChild As Integer, ByVal dwEventThread As Integer, ByVal dwmsEventTime As Integer)
Const WINEVENT_OUTOFCONTEXT As Integer = 0
Const EVENT_OBJECT_CREATE As Integer = &H8000
Private hook As IntPtr = IntPtr.Zero
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
hook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, IntPtr.Zero, AddressOf WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT)
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles MyBase.FormClosed
UnhookWinEvent(hook)
End Sub
Private Sub WinEventProc(ByVal hWinEventHook As IntPtr, ByVal eventType As Integer, ByVal hwnd As IntPtr, ByVal idObject As Integer, ByVal idChild As Integer, ByVal dwEventThread As Integer, ByVal dwmsEventTime As Integer)
Dim windowTitle As String = GetWindowText(hwnd)
If windowTitle <> "" AndAlso IsPopupWindow(hwnd) Then
msgbox("New Window Detected")
End If
End Sub
Private Function IsPopupWindow(ByVal hwnd As IntPtr) As Boolean
Dim style As Long = GetWindowLong(hwnd, GWL_STYLE)
Return (style And WS_POPUP) = WS_POPUP
End Function
Declare Auto Function GetWindowLong Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
Private Const GWL_STYLE As Integer = -16
Private Const WS_POPUP As Long = &H80000000
Private Function GetWindowText(ByVal hwnd As IntPtr) As String
Dim textLength As Integer = GetWindowTextLength(hwnd) + 1
Dim text As String = New String(" "c, textLength)
GetWindowText(hwnd, text, textLength)
Return text.Trim()
End Function
Declare Auto Function GetWindowText Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer
Declare Auto Function GetWindowTextLength Lib "user32.dll" (ByVal hWnd As IntPtr) As Integer
What approach could I use to better listen for the creation of new program windows? Or, how could I fix my code?
EVENT_OBJECT_CREATE gets triggered for all kinds of objects, not just windows. You will have to retrieve the created object's window class name via GetClassName() and ignore whichever classes you don't want to process. Menus have a standard class name of #32768.
I would like to get the scaling factor of a secondary screen.
With this piece of code I get the right information for the primary monitor:
Private Declare Function GetDeviceCaps Lib "gdi32.dll" (ByVal hdc As IntPtr, ByVal nIndex As Integer) As Integer
Private Declare Function GetDCEx Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal hrgnClip As IntPtr, ByVal DeviceContextValues As DeviceContextValues) As IntPtr
Dim desktop As IntPtr = GetDCEx(0, 0, DeviceContextValues.Window)
Dim scalling As Double = GetDeviceCaps(desktop, 118) / GetDeviceCaps(desktop, 8)
But how can I get the same information for the 2nd monitor?
Which parameters in the GetDCEx function?
thanks it's help me this is the solution :
<DllImport("gdi32.dll")>
Public Shared Function GetDeviceCaps(ByVal hDC As IntPtr, ByVal nIndex As Integer) As Integer
End Function
<DllImport("gdi32.dll", SetLastError:=True, CharSet:=CharSet.Ansi)>
Public Shared Function CreateDC(<MarshalAs(UnmanagedType.LPStr)> lpszDriver As String,
<MarshalAs(UnmanagedType.LPStr)> lpszDevice As String,
<MarshalAs(UnmanagedType.LPStr)> lpszOutput As String,
lpInitData As IntPtr) As IntPtr
End Function
Public Shared Function GetScalleFactor(index As Integer) As Double
Dim desktop As IntPtr = CreateDC(Screen.AllScreens(index).DeviceName, Nothing, Nothing, IntPtr.Zero)
Return GetDeviceCaps(desktop, 118) / GetDeviceCaps(desktop, 8)
End Function
I want to send a leftbutton-mouseclick to a (specific) program but it doesn't work. when i tried my code on several other apps it worked without any major changes.
this is my Declaration:
Public Class Win32
#Region "Methods And Functions Declaration"
Public Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal IpClassName As String, ByVal IpWindowName As String) As Int32
Public Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Int32) As Int32
Public Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As Int32, ByVal hWnd2 As Int32, ByVal lpsz1 As String, ByVal lpsz2 As String) As Int32
Public Declare Function EnumChildWindows Lib "user32.dll" (ByVal hWndParent As Int32, ByVal lpEnumFunc As Int32, ByVal lParam As Int32) As Int32
Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByRef lParam As Int32) As Int32
Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByRef lParam As String) As Int32
#End Region
#Region "Messages"
Public Const BM_CLICK As Int32 = &HF5
Public Const WM_NCLBUTTONDOWN As Int32 = &HA1
Public Const WM_NCHITTEST As Int32 = &H84
Public Const WM_NCLBUTTONDBLCLK As Int32 = &HA3
Public Const WM_NCLBUTTONUP As Int32 = &HA2
Public Const WM_SETFOCUS As Long = &H7
Public Const WM_SETTEXT As Long = &HC
Public Const WM_NCRBUTTONDOWN As Int32 = &HA4
#End Region
the actual code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Druck Eingeben
Dim Hwnd As Integer = Win32.FindWindow(Nothing, "V1.22 BMTS Prüfstand 2")
If (Not Hwnd = 0) Then
Dim HwndInfo As Integer = Win32.FindWindowEx(Hwnd, Nothing, "TGroupBox", "Info")
If Not HwndInfo = 0 Then
Dim ccHwnd As Integer = Win32.FindWindowEx(HwndInfo, Nothing, "TPanel", Nothing)
If Not ccHwnd = 0 Then
Dim cccHwnd As Integer = Win32.FindWindowEx(ccHwnd, Nothing, "Tedit", Nothing)
If Not cccHwnd = 0 Then
Win32.SetForegroundWindow(cccHwnd)
SendKeys.Send("990")
Else
MessageBox.Show("Bitte Starte erst die Programme")
End If
Else
MessageBox.Show("Bitte Starte erst die Programme")
End If
Else
MessageBox.Show("Bitte Starte erst die Programme")
End If
Win32.SetForegroundWindow(HwndInfo)
SendKeys.Send("999")
Else
MessageBox.Show("Bitte Starte erst die Programme")
End If
'Startbutton Klicken
Dim HwndFunktion As Integer = Win32.FindWindowEx(Hwnd, Nothing, "TGroupBox", "Funktion")
If Not HwndFunktion = 0 Then
Dim cHwnd As Integer = Win32.FindWindowEx(HwndFunktion, Nothing, "TButton", "S T A R T")
If Not cHwnd = 0 Then
Win32.SetForegroundWindow(cHwnd)
Win32.SendMessage(cHwnd, Win32.WM_SETFOCUS, 0, 0)
Win32.SendMessage(cHwnd, Win32.WM_NCLBUTTONDBLCLK, 0, 0)
Win32.SendMessage(cHwnd, Win32.WM_NCLBUTTONDBLCLK, 0, 0)
Win32.SendMessage(cHwnd, Win32.WM_NCLBUTTONDOWN, 0, 0)
Win32.SendMessage(cHwnd, Win32.WM_SETTEXT, 0, "6")
Else
MessageBox.Show("Bitte Starte erst die Programme")
End If
Else
MessageBox.Show("Bitte Starte erst die Programme")
End If
End Sub
To the Program itself: It runs on an old test bench, on win 7.
I think it depends on .net 3.5 but i don't have detailed information about it.
As a test, i filled a textbox with my code and even changed the label of the button. Just the click function doesn't work.
First I tried in with mouse positioning, now directly with the handles.
It doesn't work either way.
Please remember, the code works fine on a few tested Programs (except the one I need it for).
i want to check if the active window handle is password box.
this function returns me the active control handle of the active window:
Imports System.Runtime.InteropServices
Public Class FormMain
Inherits Form
Private Declare Function GetForegroundWindow Lib "user32.dll" () As IntPtr
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal ProcessId As IntPtr) As IntPtr
Private Declare Function AttachThreadInput Lib "user32.dll" (ByVal idAttach As IntPtr, ByVal idAttachTo As IntPtr, ByVal fAttach As Boolean) As IntPtr
Private Declare Function GetFocus Lib "user32.dll" () As IntPtr
Public Sub New()
MyBase.New
InitializeComponent
End Sub
Private Sub timerUpdate_Tick(ByVal sender As Object, ByVal e As EventArgs)
labelHandle.Text = ("hWnd: " + FocusedControlInActiveWindow.ToString)
End Sub
Private Function FocusedControlInActiveWindow() As IntPtr
Dim activeWindowHandle As IntPtr = GetForegroundWindow
Dim activeWindowThread As IntPtr = GetWindowThreadProcessId(activeWindowHandle, IntPtr.Zero)
Dim thisWindowThread As IntPtr = GetWindowThreadProcessId(Me.Handle, IntPtr.Zero)
AttachThreadInput(activeWindowThread, thisWindowThread, true)
Dim focusedControlHandle As IntPtr = GetFocus
AttachThreadInput(activeWindowThread, thisWindowThread, false)
Return focusedControlHandle
End Function
End Class
now i want to do something like:
if FocusedControlInActiveWindow() <> intptr.zero then
dim IsPass as boolean = isPassword(FocusedControlInActiveWindow())
if IsPass then
msgbox("yes")
else
msgbox ("no")
end if
end if
how can i check if the foucsed control in the active window text is passwordcahr?
If you want to check if a Windows Edit Control has the ES_PASSWORD style, this is how to do it:
Public Shared Function HasPasswordStyle(ByVal hWnd As IntPtr) As Boolean
Return ((GetWindowLong(hWnd, GWL_STYLE) And ES_PASSWORD) <> 0)
End Function
<DllImport("user32.dll")> _
Private Shared Function GetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
End Function
Private Const ES_PASSWORD As Integer = 32
Private Const GWL_STYLE As Integer = -16
I'm attempting to intercept and interrupt mouse events. Lets say I wanted to disable the right mouse button down event, or even the mouse move event. I haven't been able to figure out the interrupting part.
I am using the (I assume pretty widely used) following code for Global Hooking of the mouse.
Private Structure MSLLHOOKSTRUCT
Public pt As Point
Public mouseData As Int32
Public flags As Int32
Public time As Int32
Public extra As IntPtr
End Structure
Private _mouseHook As IntPtr
Private Const WH_MOUSE_LL As Int32 = 14
Private Delegate Function MouseHookDelegate(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
<MarshalAs(UnmanagedType.FunctionPtr)> Private _mouseProc As MouseHookDelegate
Private Declare Function SetWindowsHookExW Lib "user32.dll" (ByVal idHook As Int32, ByVal HookProc As MouseHookDelegate, ByVal hInstance As IntPtr, ByVal wParam As Int32) As IntPtr
Private Declare Function UnhookWindowsHookEx Lib "user32.dll" (ByVal hook As IntPtr) As Boolean
Private Declare Function CallNextHookEx Lib "user32.dll" (ByVal idHook As Int32, ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
Private Declare Function GetCurrentThreadId Lib "kernel32.dll" () As Integer
Private Declare Function GetModuleHandleW Lib "kernel32.dll" (ByVal fakezero As IntPtr) As IntPtr
Public Function HookMouse() As Boolean
Debug.Print("Mouse Hooked")
If _mouseHook = IntPtr.Zero Then
_mouseProc = New MouseHookDelegate(AddressOf MouseHookProc)
_mouseHook = SetWindowsHookExW(WH_MOUSE_LL, _mouseProc, GetModuleHandleW(IntPtr.Zero), 0)
End If
Return _mouseHook <> IntPtr.Zero
End Function
Public Sub UnHookMouse()
Debug.Print("Mouse UnHooked")
If _mouseHook = IntPtr.Zero Then Return
UnhookWindowsHookEx(_mouseHook)
_mouseHook = IntPtr.Zero
End Sub
Private Function MouseHookProc(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
'Debug.Print("Message = {0}, x={1}, y={2}", wParam.ToInt32, lParam.pt.X, lParam.pt.Y)
If wParam.ToInt32 = 513 Then
'''interrupt the left mouse button event here, but don't know what to return to do so.
End If
Return CallNextHookEx(WH_MOUSE_LL, nCode, wParam, lParam)
End Function
Return 1 - sorry for posting this.