Hei,
Miten saisin kuvassa (http://img28.imageshack.us/img28/9062/84489330.
FindWindowilla varmaan sais jotenki ainakin koko tehtäväpalkin kahvan, jos ei muuten, mutta miten tuon tietyn alueen? Miten selvitän tuon kohdan "class namen"?
Pelkään, että tuo alue on samaa objektia tuon pikakäynnistyspalkin kanssa.
Ideoita?
GetWindowRectillä saa sitten koordinaatit kunhan kahva (hwnd) löytyy..
Olis tyhmää laittaa käyttäjä valitsemaan tuo alue ruudulta, vaikka se pitäisikin tehdä vaan ohjelman ensimmäisellä käynnistyskerralla (ja aina kun tehtävpalkin asetuksia säätelee)..
(Jaa missä kuvassa? Mod. siirsi linkin fiksumpaan väliin.)
Tämmönen funktio löyty, mutta ei tolla taida saada vain tuon yhden osan sijaintia selville.. http://msdn.microsoft.com/en-us/library/bb762108(VS.85).aspx
Meinasitko vielä että pitäisi toimia myös Windows 7:ssä se, mitä tahansa oletkaan tavoittelemassa?
Moro JussiR!
Tutustu näihin työkaluihin ja tutustu sitten AccessibleObject-luokkaan (Accessibility.dll)
Microsoft Spy++:lla katsoin ja kyllä sillä oli ihan oma kahva. Ainakin Windows XP:ssä.
Tuon alueen class name on ToolbarWindow32 ja caption "Avoimet sovellukset".
Toivottavasti saan kahvan selville ilman, että joudun etsimään sitä tuon captionin perusteella... En nyt muista ulkoa kuinka FindWindowia käytettiin (olen töissä).
Kiitos Nea, pitää katsoa jossain vaiheessa.
Merri: Jos alueella on oma hWnd myös W7:ssa, niin ei ole iso homma laittaa toimimaan myös sillä käyttöjärjestelmällä.
Tämän koodin pitäis testiksi liikuttaa hiiri kohtaan, jossa tuo alue alkaa.
Mutta en ymmärrä miksi heittää virheen "User-defined type may not be passed ByVal", kohdassa, jossa käytän GetWindowRectiä (tekstin "BarRect" kohdalla).
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Integer, ByVal lpRect As RECT) As Integer
Private Declare Function SetCursorPos Lib "user32.dll" (ByVal x As Long, ByVal y As Long) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public Sub test()
Dim BarRect As RECT
GetWindowRect BarHwnd, BarRect '<- Tuossa noin
SetCursorPos BarRect.Left, BarRect.Top
End Sub
Public Function BarHwnd()
Dim TaskBar As String
Dim BarChild As String
TaskBar = FindWindow("Shell_TrayWnd", vbNullString)
BarChild = FindWindowEx(TaskBar, 0&, "ReBarWindow32", vbNullString)
BarHwnd = FindWindowEx(BarChild, 0&, "MSTaskSwWClass", vbNullString)
End FunctionJussiR kirjoitti:
Mutta en ymmärrä miksi heittää virheen "User-defined type may not be passed ByVal"
Koska itse määriteltyjä tyyppejä ei voi välittää arvoina (ByVal) vaan ainoastaan viittauksina (ByRef). Muutenkaan lpRect ei koskaan ole ByVal, vaan sen on oltava ByRef. Voithan ajatella asiaa järjelläkin: ByVal tarkoittaa, että vain muuttujan arvo välitetään funktiolle, ja eihän se silloin voi tallentaa kyseiseen muuttujaan tietoa. ByRef tarkoittaa viittauksen (osoittimen) välittämistä, jolloin funktio voi muokata muuttujaa, tuossa tapauksessa tallentaa siihen pyydetyn suorakulmion.
Kiitoksia vastauksista!
Tässä koodi joka laittaa hiiren kohtaan, jossa tuo alue alkaa (toimii myös Windows 7:ssa, mutta samaan alueeseen kuuluu ohjelmat, joista on valittu "pin to taskbar", vaikka ne eivät olisi käynnissä).
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Integer, ByVal hWnd2 As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Integer, ByRef lpRect As RECT) As Integer
Private Declare Function SetCursorPos Lib "user32.dll" (ByVal x As Long, ByVal y As Long) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Function BarRectangle(ByRef barRect As RECT)
Dim TaskBar As String
Dim BarChild As String
TaskBar = FindWindow("Shell_TrayWnd", vbNullString)
BarChild = FindWindowEx(TaskBar, 0&, "ReBarWindow32", vbNullString)
BarHwnd = FindWindowEx(BarChild, 0&, "MSTaskSwWClass", vbNullString)
GetWindowRect BarHwnd, barRect
End Function
Private Sub Form_Load()
Dim taskRect As RECT
BarRectangle taskRect
SetCursorPos taskRect.Left, taskRect.Top
End Sub... ja projekti jatkuu. =)
Moikka taas JussiR!
Tässä sinulle kevyt wrapperi ja testiohjelma jolla voit hieman vauhdittaa edellisessä viestissäni mainitsemaani jutskaan tutustumista...elikäs imppaa täältä AccLayer.zip, pura paketti ja lue ReadMe.txt
VB.NET-testiprojekti (AccLayerTest)
Imports Accessibility
Imports AccLayer
Public Partial Class MainForm
Public Sub New()
Me.InitializeComponent()
End Sub
Sub Button1Click(sender As Object, e As EventArgs)
Dim procName As String = "notepad"
Dim appFolder As String = ""
If appFolder <> String.Empty Then
appFolder += "\"
End If
KillProcess(procName)
Dim fullPath As String = appFolder + procName + ".exe"
StartProcess(fullPath)
Static cnt As Integer
Back:
cnt += 1
Dim MyObject As IAccessible = _
AccLayer.Acc.GetAccessibleObjectFromHandle _
(GetProcessHandle(procName))
Try
MyObject.accHitTest(1, 1) 'klikataan (x,y)
' Tutki: MyObject. - mitä laatikkoon
' ilmestyy ja Googleta
Catch ex As Exception
If cnt < 20 Then
GoTo Back
Else
MsgBox("EI TOIMI")
End If
End Try
cnt = 0
End Sub
Sub StartProcess(ByVal fullPath As String)
Dim sInfo As New ProcessStartInfo
With sInfo
.FileName = fullPath
.WindowStyle = ProcessWindowStyle.Normal
End With
Dim proc As New Process
With proc
.StartInfo = sInfo
.Start
End With
End Sub
Sub KillProcess(ByVal AppName As String)
Dim procs() As Process = Process.GetProcesses()
For Each proc As Process In procs
With proc
If .ProcessName.ToLower _
= AppName.ToLower Then
.Kill
End If
End With
Next
procs = Nothing
End Sub
Function GetProcessHandle(ByVal AppName As String) As Object
Dim procs() As Process = Process.GetProcesses()
For Each proc As Process In procs
With proc
If .ProcessName.ToLower _
= AppName.ToLower Then
Return .MainWindowHandle
Exit Function
End If
End With
Next
procs = Nothing
Return Nothing
End Function
End ClassKyllä se nyt tyrkyttää sitä. Viime threadissakin =D
Kai sitä sitten pitää kokeilla.. Ja vaihtaa jossain välissä .NET:iin..
Aihe on jo aika vanha, joten et voi enää vastata siihen.