Hýbání s myší   zodpovězená otázka

VB.NET, WinForms

Zdravím, dělám na takové blbůstce (chci si ze svého HTC diamond udělat dálkové ovládání myši pro svůj počítač), ale zarazil jsem se hned na začátku a to jak správně hýbat s myší.

Vím jak se pohybovat po souřadnici X, ale pro mě z neznámého důvodu se mi souřadnice Y vždy nastaví na 0 (a vím určitě že nejsem mimo rozsah rozlišení obrazovky)

Pohybu realizuji takto:

Public Class Form1

    Structure POINTAPI
        Dim x As Long
        Dim y As Long
    End Structure
    Dim polohaMysi As POINTAPI

    Private Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long



    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Select Case e.KeyCode

            Case Keys.Up
                Call SetCursorPos(Control.MousePosition.X, Control.MousePosition.Y + 10)
            Case Keys.Down
                Call SetCursorPos(Control.MousePosition.X, Control.MousePosition.Y - 10)
            Case Keys.Left
                Call SetCursorPos(Control.MousePosition.X - 10, Control.MousePosition.Y)
            Case Keys.Right
                Call SetCursorPos(Control.MousePosition.X + 10, Control.MousePosition.Y)
            Case Keys.Enter
                MsgBox(Control.MousePosition.X & ":" & Control.MousePosition.Y)
        End Select
    End Sub

End Class

Nulová souřadnice Y se nastaví i v případě, že do volání funkce natvrdo napíšu třeba 200.

Nenašel jsem zde žádou chybu. Nemohl by být problém v tom, že mám 2 monitory?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Teoreticky by to tím být mohlo. Pokud máte grafickou kartu NVIDIA, zkuste si nastavit režim více monitorů na Single Display nebo Clone. Jinak bych doporučoval používat statickou vlastnost Cursor.Position, když to jde Frameworkovsky, není nutné Windows API.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Mám grafickou kartu ATI. Problém přetrvává i když jsem druhý monitor zakázal. Ale problém bych čekal spíše u souřadnice X. Ta ale funguje tak jak má, tzn. když dojede na pravý kraj primárního monitoru při dalším kroku kurzor přeskočí na druhý monitor.

Zkusím tedy ještě tu Frameworkovskou funkci o ní jsem nevědel:)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

V API definici změňte na konci As Long na As Integer anebo poslechněte p. Linharta

  Private Sub Form1_KeyDown(ByVal sender As Object, _ 
     ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
    Select Case e.KeyCode
      Case Keys.Up
        Cursor.Position = New Point(Control.MousePosition.X, Control.MousePosition.Y - 10)
      Case Keys.Down
        Cursor.Position = New Point(Control.MousePosition.X, Control.MousePosition.Y + 10)
      Case Keys.Left
        Cursor.Position = New Point(Control.MousePosition.X - 10, Control.MousePosition.Y)
      Case Keys.Right
        Cursor.Position = New Point(Control.MousePosition.X + 10, Control.MousePosition.Y)
      Case Keys.Enter
        MsgBox(Control.MousePosition.X & ":" & Control.MousePosition.Y)
     End Select

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Změna z long na integer nepomohla, chová se to stejně, ale použil jsem tu funkci Cursor.Position a je to ok. Stejně by mě zajímalo kde je chyba, zkusím to pak ještě na svém PC doma.

Děkuji oběma:)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

tak definice souřadnic, ne funkce, změňte na Integer - někde se tu již o nutných změnách typu v API píše.

Ještě budete muset zaměnit znaménka u kroku v Y souřadnici

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ano máte pravdu, už jsem si všimnul že mám prohozené směry. Neuvědomil jsem si kde je umístěn počátek osy y:)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jinak měl jste pravdu, stačilo v deklaraci funkce změnit long na integer.

Pro úplnost sem přidávám správný kód, třeba se bude někomu hodit.

Zde je pohyb myši pomocí API:

    Structure POINTAPI
        Dim x As Integer
        Dim y As Integer
    End Structure


    Private Declare Function SetCursorPos Lib "user32" (ByVal x As Integer, ByVal y As Integer) As Long



    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Select Case e.KeyCode

            Case Keys.Up
                Call SetCursorPos(Control.MousePosition.X, Control.MousePosition.Y - 10)
            Case Keys.Down
                Call SetCursorPos(Control.MousePosition.X, Control.MousePosition.Y + 10)
            Case Keys.Left
                Call SetCursorPos(Control.MousePosition.X - 10, Control.MousePosition.Y)
            Case Keys.Right
                Call SetCursorPos(Control.MousePosition.X + 10, Control.MousePosition.Y)
        End Select
    End Sub

A zde pomocí Frameworku:

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Select Case e.KeyCode




            Case Keys.Up
                Cursor.Position = New Point(Cursor.Position.X, Cursor.Position.Y - 10)
            Case Keys.Down
                Cursor.Position = New Point(Cursor.Position.X, Cursor.Position.Y + 10)
            Case Keys.Left
                Cursor.Position = New Point(Cursor.Position.X - 10, Cursor.Position.Y)
            Case Keys.Right
                Cursor.Position = New Point(Cursor.Position.X + 10, Cursor.Position.Y)
        End Select

    End Sub

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zrovna tohle jsem dneska hledal. Škoda že jsem se nekouknul dřív na dnešní příspěvky v diskuzi :)

Hýbání myší mám vyřešené. Ale potřeboval bych kliknout s myší (levým/pravým tlačítkem) a abych mohl nastavit jen "stisknutí tlačítka myši" a "jen puštění tlačítka myši".

Našel jsem tohle: http://www.vbnet.cz/forum-tema--1868-kli... ale nevím co dát místo "Handle" aby mi to kliklo na aktuální pozici kurzoru.

Pomožte prosím. Případně díky ;)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak už jsem na to přišel. Použil jsem nakonec kód z VB6. Jen pro doplnění:

Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)

    Const MOUSEEVENTF_LEFTDOWN = &H2
    Const MOUSEEVENTF_LEFTUP = &H4
    Const MOUSEEVENTF_MIDDLEDOWN = &H20
    Const MOUSEEVENTF_MIDDLEUP = &H40
    Const MOUSEEVENTF_RIGHTDOWN = &H8
    Const MOUSEEVENTF_RIGHTUP = &H10
    Dim cButt
    Dim dwEI


'použití
mouse_event(MOUSEEVENTF_LEFTDOWN, 0&, 0&, cButt, dwEI)
mouse_event(MOUSEEVENTF_LEFTUP, 0&, 0&, cButt, dwEI)

Ale abych se přiznal, nevím k čemu je "cButt" a "dwEI" a vlastně ani to 0& (dx a dy). Neukamenujte mě... :(

Hlavně že to funguje :)

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Mně se podařilo vyřešit kliknutí myší (jsou to dvě API funkce, jedna na stlačení tlačítka a druhá na uvolnění). Funguje to dobře, ale zatím se mi nepodařilo rozchodit abych se zmáčknutým tlačítkem mohl třeba vzít okno a posunout ho.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To nebude vůbec jednoduché. Pravděpodobně bude třeba odeslat zprávu WM_LBUTTONDOWN do aktivní aplikace při stisku tlačítka myši a zprávu WM_LBUTTONUP při uvolnění tlačítka myši. To se udělá pomocí Windows API funkce PostMessage, handle které bude potřeba pro tuto funkci se zjistí pomocí GetForegroundWindow. Taky se může stát že to nebude fungovat, pouštíte se do zbytečně složitých věcí.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Takže se na to s největší pravděpodobností vykašlu a udělám jenom klikání:)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zbavit se okna jsem řešil buď jeho lokací mimo obrazovku nebo zprůhledněním.

Nevím, kam směřujete, ale myslím, že narazíte na problém s obejitím systému. Jakmile nastane cokoliv, co zachytí systém, aplikace již nebude aktivní.

    Me.Opacity = 0
    Me.WindowState = FormWindowState.Maximized
    Me.TopMost = True

Jak v aplikaci ošetřit údálosti, na které přednostně reagují Windows, se tu již řešilo.

nahlásit spamnahlásit spam -2 / 2 odpovědětodpovědět

Co se týká toho problému zneaktivnění aplikace myslel jsem, že by se to vyřešilo tím že bych to napsal jako službu. Ale možná to je blbost. O napsání služby se snažím vůbec poprvé, takže si asi nejdřív o tom něco přečtu abych věděl jaké jsou její možnosti a odlišnosti oproti klasické win form nebo console aplikaci.

Děkuji všem za reakce.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Služba se od běžné aplikace liší hlavně tím, že běží na pozadí bez nutnosti přihlášení uživatele. Sama o sobě nemá žádné uživatelské rozhraní. Hodí se tedy na všelijaké systémové věci.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Já osobně bych použil normální form a hned po startu ho minimalizoval do systray (nikdy nevíš kdy se může hodit). A nebo bych form vymazal a program napsal do modulu.

Ve VB6 to takhle šlo (stačilo ve vlastnostech projektu nastavit Startup object na požadovanou funkci) nevím jak ve VB.NET.

Každopádně to ber jako radu amatéra ;)

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

No přesně takhle jsem to udělal (dokonce ještě před přečtením Vašeho příspěvku) :) Jinak ovládání myši funguje skvěle, dokonce není ani problém s přesouváním oken:) Jediné co se mi zatím nepodařilo rozchodit je Gsenzor. Ale to je kvůli tomu, že jsem si chtěl potřebné knihovny stáhnout s hrou Tomáše Hercega (ty helikoptérky). Ke spuštění musím mít VS 2008 standart nebo vyšší a já mám 2005 profesionál a v současnosti mám nějáký problém se stahováním od microsoftu (mají 90 denná trial verzi VS 2008 profesional). Jinak co se týče apliakce samotné je to velice jednoduché, hodně jsem se inspiroval kreslící tabulí, tam je základ všeho (doteď pro mě byl síťový přenos tabu). Až to doladim můžu poskytnou zdroják na další blbnutí pokud bude zájem:)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dobrý den,

chtěl jsem se jen zeptat, jak často berete údaje ze senzoru ? Pohrával jsem si s SDK Gsenzoru z příkladu Helicopter a narazil jsem na následující. Načtení všech tří vektorů ze senzoru trvá cca 10ms, např. takto:

            gx = sensor.GetRawSensorData.TiltX
            gy = sensor.GetRawSensorData.TiltY
            gz = sensor.GetRawSensorData.TiltZ

Předpokládal jsem tedy, že mohu načítat data např s frekvencí 50Hz (každých 20ms) ale to je omyl. Nejrychlejší opakování je každých 40ms (25Hz) což mě zaráží, když výše uvedený kód potřebuje kolem 10ms. Nakonec jsem to zkusil tak , že v samostaném vlákně běží nekonečná smyčka, která updatuje proměnné a po skončení vlákno na 40ms uspím. Protože s kratším časem to prostě nejde...

J.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zdravim taky řešim klikani, ale když tam napisu tento kod (mouse_event) atd. Tak mi to hodi chybu::

"A call to PInvoke function 'Automat!Automat.Form1::mouse_event' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature."

Nemam paru o co mu jde..

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback