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 Function
JussiR 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 Class
Kyllä 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.