[gelöst] Mausrad + Keyboard auslesen

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Qnode
Beiträge: 67
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

[gelöst] Mausrad + Keyboard auslesen

Beitrag von Qnode »

Hey,

… ich mal wieder und meine Fragen... /:->

Zum Beispiel in Browsern kann man mit Strg + Mausrad die Schriftgröße ändern. Ich würde das gerne für einen Formular-Resize in PB umsetzen (bzw. mein Frauchen fände das cool für ein Tool, was ich für sie grade schreibe 8) ).
Habe mal ein bisserl geforscht und gegoogelt, aber keinen so richtigen Ansatz gefunden, wie man speziell Änderungen des Mausrades in einer "normalen" Anwendung auslesen kann. In den normalen Events hat man #PB_Event(type)_LeftClick usw. aber kein _MouseWheel-Event oder so. Dann gibt es noch die Mouse-Bibliothek, bei der man das Mausrad mittels MouseWheel() auslesen kann, aber in der Hilfe heißt es: "Verwenden Sie die Befehle dieser Bibliothek nicht in einer regulären Applikation"(... warum eigentlich nicht?). Und dann müsste man dazu noch ermitteln, ob gleichzeitig die Strg-Taste gedrückt ist... Arrrrgh.

Nun ja, wenns nicht geht, dann geht es halt nicht. Oder habt ihr da noch einen Tipp? Ich habe die dumpfe Vermutung, dass sich sowas vielleicht durch Zugriff auf die WinAPI machen lässt, aber von der habe ich keine Ahnung (bin ja froh, wenn ich meinen Basic-Code verstehe). Mal abgesehen davon, dass ich immer versuche, Multiplatform zu bleiben. Ist zwar nicht zwingend, aber ich verwalte z.B. unsere häuslichen Finanzen mit einer selbst zusammengematschten Visual Basic 2010 Datenbankanwendung. Was mich stört, weil es mich auf Windows fixiert. Ich fänd's besser, wenn meine selbstgeschraubten Sache ohne größere Anpassungen auch unter Linux liefen (was ich z.T. auch schon mit Lazarus/FPC hinbekommen habe und mir auch von Pure Basic verspreche, das mir viel Freude macht).

EDIT: Habe in der WinAPI-Library von RSBasic schon mal die Windows-Variante gefunden, wie man generell sehen kann, ob das Mausrad auf oder ab bewegt wurde. Das ist schon mal ein Anfang. Jetzt nur noch rauskriegen, wie man die Ticks herausbekommt und wie man gleichzeitig Funktionstasten abfragt... (wenn man sich denn auf Windows beschränkt). Auf jeden Fall mein Dank an RSBasic: da wär ich im Leben nicht drauf gekommen!
Zuletzt geändert von Qnode am 10.01.2019 19:29, insgesamt 1-mal geändert.
Benutzeravatar
tft
Beiträge: 605
Registriert: 08.09.2004 20:18
Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
Wohnort: Dachsen
Kontaktdaten:

Re: Mausrad + Keyboard auslesen

Beitrag von tft »

Hallo,

in meinen Aktuellen Game Projekt verwende ich folgenden Code unter Windows.

Code: Alles auswählen


#WM_MOUSEWHEEL_UP      = 7864320
#WM_MOUSEWHEEL_DOWN = 4287102976
#NoKeyRepeat                    = 1075838977

  Repeat
    Event = WindowEvent()
    If Event
      
      ;{ Event Handling der Sytemnachrichten
      
      If EventWindow() = #MainWindow
        Select Event
          Case #PB_Event_Gadget
 
          Case #WM_KEYDOWN ; Taste wurde gedrückt
            
            ;Repeat unterdrückung
            If EventlParam()<>#NoKeyRepeat
              Select EventwParam()
                Case #VK_D  
                  T_D = 1
                Case #VK_A
                  T_A = 1
                Case #VK_S  
                  T_S = 1
                Case #VK_W
                  T_W = 1
                Case #ESC                     ; Programm beenden bei drücken der ESC Taste
                  Quit = 1
               EndSelect
            EndIf
          
          Case #WM_KEYUP ; Taste wurde losgelassen
            Select EventwParam()
              Case #VK_D  
                T_D = 0
              Case #VK_A
                T_A = 0
              Case #VK_S  
                T_S = 0
              Case #VK_W
                T_W = 0
            EndSelect
            
          Case #WM_LBUTTONDOWN  
            Debug "#WM_LBUTTONDOWN " + Str(EventwParam()) 
            Debug "#WM_LBUTTONDOWN " + Str(EventlParam()) 
          Case #WM_LBUTTONUP  
            Debug "#WM_LBUTTONUP " + Str(EventwParam()) 
            Debug "#WM_LBUTTONUP " + Str(EventlParam()) 
          Case #WM_MOUSEWHEEL
            Debug "#WM_MOUSEWHEEL w" + Str(EventwParam()) 
            Debug "#WM_MOUSEWHEEL l" + Str(EventlParam()) 
            Select EventwParam()
              Case #WM_MOUSEWHEEL_UP
                SpeedZ=SpeedZ+0.01
              Case #WM_MOUSEWHEEL_DOWN
                SpeedZ=SpeedZ-0.01
            EndSelect
              
          Case #PB_Event_CloseWindow      ; Programm beenden bei SystemCloseWindow GadGet
            Quit = 1
          Default
        EndSelect
        
      EndIf
      
      ;}
      
    Else
      Delay(1)                           ; Wenn keine Events vorliegen dann dem System etwas Zeit einräumen.
    EndIf
  Until Event = 0

  ; Hole Mouseposition aus dem System, Die Position wird immer actualisiert und enthält auch die Position
  ; wenn die Mouse nicht im Fenster oder sichtbar ist.
  GetCursorPos_(st.POINT) 
  mx=st\x 
  my=st\y 

du musst das noch für dich anpassen, aber das sollte machbar sein.

Gruss TFT
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak :-)
Benutzeravatar
Qnode
Beiträge: 67
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Re: Mausrad + Keyboard auslesen

Beitrag von Qnode »

Danke schön. Hab den Code bei mir zum Laufen gebracht und probiere fröhlich damit rum.
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: Mausrad + Keyboard auslesen

Beitrag von Shardik »

Ich habe im englischen Forum schon einmal dieses Multiplattform-Beispiel mit den entsprechenden API-Befehlen für Linux, MacOS und Windows gezeigt, das die Mausrad-Bewegung und -Richtung in einem ListIconGadget entdeckt.
Benutzeravatar
Qnode
Beiträge: 67
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Re: Mausrad + Keyboard auslesen

Beitrag von Qnode »

Hey TFT,

zu deinem Code habe ich noch ein paar Fragen:
Über #VK_CONTROL kriege ich schon mal raus, ob die Strg-Taste gedrückt wurde... aber wie finde ich heraus, ob Mausrad und Strg-Taste gemeinsam verwendet wurden? Hab mal rumprobiert, klappt aber nicht.
Übrigens: Laut Hilfe sind EventlParam und EventwParam deprecated (Diese Funktion wird nicht mehr unterstützt und sollte in neuen Projekten nicht verwendet werden. Nutzen Sie einen Callback mittels SetWindowCallback(), um volle Kontrolle über die Windows-Nachrichten (messages) zu erhalten). Könnte das für die Zukunft ein Problem sein?
Zuletzt geändert von Qnode am 09.01.2019 23:38, insgesamt 1-mal geändert.
Benutzeravatar
Qnode
Beiträge: 67
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Re: Mausrad + Keyboard auslesen

Beitrag von Qnode »

Hallo Shardik,

toll, dass du mir diesen Mulit-Platform-Code verlinkt hast! Ich habe ihn mir jetzt angesehen und grob verstanden (mehr geben meine Kenntnisse nicht her, sorry). Was ich (noch) nicht verstehe: wie kann ich abgleichen, ob gleichzeitig die Strg-Taste gedrückt wurde? Ich werde auch selbst weiterstöbern, habe aber den dumpfen Verdacht, dass ich das nicht rauskriege.

Versteht mich bitte nicht falsch: Ich bin eigentlich nicht der Typ, der nach Copy-Paste-Lösungen sucht. Ich hoffe, das bringe ich in meinen Posts auch ein wenig rüber. Aber dieser Griff in die API's der Betriebssysteme ist wohl etwas zu hoch für mich... ich versuche trotzdem weiterhin soviel wie möglich selbst zu lösen, versprochen!
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: Mausrad + Keyboard auslesen

Beitrag von Shardik »

Qnode hat geschrieben:Was ich (noch) nicht verstehe: wie kann ich abgleichen, ob gleichzeitig die Strg-Taste gedrückt wurde?
Dazu kannst Du die Windows-API Funktion

Code: Alles auswählen

GetAsyncKeyState_(#VK_LCONTROL) & $8000
verwenden, die $8000 zurückgibt, wenn die linke <Strg>-Taste gedrückt ist.

Ich habe Dir aus meinem verlinkten Beispiel einmal ein neues Beispiel nur für Windows (den Linux- und MacOS-Teil muss ich noch anpassen und testen) zusammengestellt, das bei gedrückter linker oder rechter <Strg>-Taste ausliest, ob das Mausrad bewegt wird und dann ein spezielles Event und einen speziellen EventType generiert, auf die in der Event-Schleife dann reagiert werden kann.

Ich lade vorher 4 Arial-Fonts in verschiedener Größe und erhöhe oder erniedrige dann CurrentFont (0 ist der kleinste geladene Font, 3 ist der größte) und ändere den neuen Font im TextGadget dann entsprechend mit SetGadgetFont() (erfolgreich getestet unter Windows 7 x64 SP1 und Windows 10 x64 mit PB 5.46 x86 im ASCII- und Unicode-Modus).

Code: Alles auswählen

EnableExplicit

#Event_ResizeText = #PB_Event_FirstCustomValue
#MaxFontID = 3
#Text = 0
#Window = 0

Enumeration 
  #EventType_MouseWheel_Down = #PB_EventType_FirstCustomValue
  #EventType_MouseWheel_Up
EndEnumeration

Procedure WindowCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
  If GetAsyncKeyState_(#VK_LCONTROL) & $8000 Or
    GetAsyncKeyState_(#VK_RCONTROL) & $8000
    If Msg = #WM_MOUSEWHEEL
      If (WParam >> 16) & $8000
        PostEvent(#Event_ResizeText, #Window, 0, #EventType_MouseWheel_Down)
      Else         
        PostEvent(#Event_ResizeText, #Window, 0, #EventType_MouseWheel_Up)
      EndIf
    EndIf
  EndIf

  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Define CurrentFont.I = 1

LoadFont(0, "Arial", 10)
LoadFont(1, "Arial", 12)
LoadFont(2, "Arial", 14)
LoadFont(3, "Arial", 18)

OpenWindow(#Window, 200, 100, 600, 140, "Mausrad-Erkennung")
TextGadget(#Text, 10, 60, WindowWidth(#Window) - 20, 30,
  "Vergrößern/verkleinern per Mausrad und <Strg>", #PB_Text_Center)
SetGadgetFont(0, FontID(CurrentFont))
SetWindowCallback(@WindowCallback(),#Window)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #Event_ResizeText
      Select EventType()
        Case #EventType_MouseWheel_Down
          If CurrentFont > 0
            CurrentFont - 1
            SetGadgetFont(0, FontID(CurrentFont))
          EndIf 
        Case #EventType_MouseWheel_Up
          If CurrentFont < #MaxFontID
            CurrentFont + 1
            SetGadgetFont(0, FontID(CurrentFont))
          EndIf 
      EndSelect
  EndSelect
ForEver
Benutzeravatar
tft
Beiträge: 605
Registriert: 08.09.2004 20:18
Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
Wohnort: Dachsen
Kontaktdaten:

Re: Mausrad + Keyboard auslesen

Beitrag von tft »

Hallo Qnode,

es ist richtig das diese Parameter als veraltet gelten. Es ist aber ... wenn überhaupt nur relevant wenn in einer neuen PB Version
nur noch CallBacks benutzt werden würde. Die Daten muss man ja auch in einem CallBack irgendwie erhalten.
Über #VK_CONTROL kriege ich schon mal raus, ob die Strg-Taste gedrückt wurde... aber wie finde ich heraus, ob Mausrad und Strg-Taste gemeinsam verwendet wurden? Hab mal rumprobiert, klappt aber nicht.
wie du in dem Code Sniped sehen kannst, werden die Tasten zustände in den "T_X" Variablen zwischen gespeichert. Jetzt braucht es nur noch eine UND verknüpfung in dieser Form.

Code: Alles auswählen

If T_A = 1 & T_Ctrl = 1 ; BeideTastengedrueckt = 1 : Else : BeideTastengedrueckt = 0 : Endif
probier es mal ... ist nicht so drastisch ... Das gleich geht auch mit dem MouseRad :-)

Gruss TFT
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak :-)
Benutzeravatar
Qnode
Beiträge: 67
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Re: Mausrad + Keyboard auslesen

Beitrag von Qnode »

Hallo Shardik, hallo Tft,

als ich hier ankam, hatte ich keine Idee, jetzt habe ich gleich zwei Lösungen. Und ich habe sogar verstanden, wie's funktioniert (auch wenn ich selbst nicht drauf gekommen wäre). Vielen Dank!
Benutzeravatar
Shardik
Beiträge: 738
Registriert: 25.01.2005 12:19

Re: [gelöst] Mausrad + Keyboard auslesen

Beitrag von Shardik »

Hier ist das versprochene Multiplattform-Beispiel. Ich habe es mit PB 5.46 im ASCII- und Unicode-Modus auf folgenden Betriebsystemen erfolgreich getestet:
- Linux Mint 18.3 'Sylvia' Cinnamon mit Gtk2 und Gtk3
- MacOS 10.6.8 'Snow Leopard'
- MacOS 10.12.6 'Sierra'
- Windows 7 SP1 x64

Code: Alles auswählen

EnableExplicit

#Event_ResizeText = #PB_Event_FirstCustomValue
#MaxFontID = 3
#Text = 0
#Window = 0

Enumeration 
  #EventType_MouseWheel_Down = #PB_EventType_FirstCustomValue
  #EventType_MouseWheel_Up
EndEnumeration

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux ; --------------------------------------------------
    ; ----- Definiert in gdkkeysyms.h
    #GDK_KEY_Control_L = $FFE3
    #GDK_KEY_Control_R = $FFE4

    ProcedureC WindowCallback(*Event.GdkEventAny, *UserData)
      Static ControlKeyDown.I

      Protected Key.I
      Protected *KeyEvent.GdkEventKey
      Protected *ScrollEvent.GdkEventScroll

      Select *Event\type
        Case #GDK_KEY_PRESS, #GDK_KEY_RELEASE
          *KeyEvent = *Event
          Key = *KeyEvent\keyval & $FFFF

          If Key = #GDK_KEY_Control_L Or Key = #GDK_KEY_Control_R
            If *Event\type = #GDK_KEY_PRESS
              ControlKeyDown = #True
            Else
              ControlKeyDown = #False
          EndIf
        Case #GDK_SCROLL
          If ControlKeyDown
            *ScrollEvent = *Event

            Select *ScrollEvent\direction
              Case #GDK_SCROLL_UP
                PostEvent(#Event_ResizeText, #Window, #Text,
                  #EventType_MouseWheel_Up)
              Case #GDK_SCROLL_DOWN
                PostEvent(#Event_ResizeText, #Window, #Text,
                  #EventType_MouseWheel_Down)
            EndSelect
          EndIf 
      EndSelect
     
      gtk_main_do_event_(*Event)
    EndProcedure
  CompilerCase #PB_OS_MacOS ; --------------------------------------------------
    #kCGEventTapOptionListenOnly = 1
    #kCGHeadInsertEventTap = 0
    #NSControlKeyMask    = 1 << 18
    #NX_SCROLLWHEELMOVED = 22
    #NX_SCROLLWHEELMOVEDMASK = 1 << #NX_SCROLLWHEELMOVED

    ImportC ""
      CGEventTapCreateForPSN(*ProcessSerialNumber, CGEventTapPlacement.I,
        CGEventTapOptions.I, CGEventMask.Q, CGEventTapCallback.I, *UserData)
      GetCurrentProcess(*ProcessSerialNumber)
    EndImport

    ProcedureC MouseWheelCallback(CGEventTapProxy.I, CGEventType.I, CGEvent.I,
      *UserData)
      Protected DeltaY.CGFloat
      Protected NSEvent.I
      Protected Point.NSPoint

      NSEvent = CocoaMessage(0, 0, "NSEvent eventWithCGEvent:", CGEvent)
      CocoaMessage(@DeltaY, NSEvent, "deltaY")

      If CocoaMessage(0, NSEvent, "modifierFlags") & #NSControlKeyMask
        If DeltaY < 0.0
          PostEvent(#Event_ResizeText, #Window, #Text,
            #EventType_MouseWheel_Down)
        Else
          PostEvent(#Event_ResizeText, #Window, #Text,
            #EventType_MouseWheel_Up)
        EndIf
      EndIf
    EndProcedure
  CompilerCase #PB_OS_Windows ; ------------------------------------------------
    Procedure WindowCallback(WindowHandle.I, Msg.I, WParam.I, LParam.I)
      If GetAsyncKeyState_(#VK_LCONTROL) & $8000 Or
        GetAsyncKeyState_(#VK_RCONTROL) & $8000
        If Msg = #WM_MOUSEWHEEL
          If (WParam >> 16) & $8000
            PostEvent(#Event_ResizeText, #Window, #Text,
              #EventType_MouseWheel_Down)
          Else         
            PostEvent(#Event_ResizeText, #Window, #Text,
              #EventType_MouseWheel_Up)
          EndIf
        EndIf
      EndIf

      ProcedureReturn #PB_ProcessPureBasicEvents
   EndProcedure
CompilerEndSelect

Define CurrentFont.I = 1

LoadFont(0, "Arial", 10)
LoadFont(1, "Arial", 12)
LoadFont(2, "Arial", 14)
LoadFont(3, "Arial", 18)

OpenWindow(0, 200, 100, 600, 140, "Mausrad-Erkennung")
TextGadget(#Text, 10, 60, WindowWidth(0) - 20, 30,
  "Vergrößern/verkleinern mit <Strg> + Mausrad", #PB_Text_Center)
SetGadgetFont(0, FontID(CurrentFont))

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    gdk_event_handler_set_(@WindowCallback(), 0, 0)
  CompilerCase #PB_OS_MacOS
    Define MachPort.I
    Define ProcessSerialNumber.Q

    GetCurrentProcess(@ProcessSerialNumber)
    MachPort = CGEventTapCreateForPSN(@ProcessSerialNumber,
      #kCGHeadInsertEventTap, #kCGEventTapOptionListenOnly,
      #NX_SCROLLWHEELMOVEDMASK, @MouseWheelCallback(), 0)

    If MachPort
      CocoaMessage(0, CocoaMessage(0, 0, "NSRunLoop currentRunLoop"),
      "addPort:", MachPort,
      "forMode:$", @"kCFRunLoopCommonModes")
    EndIf
  CompilerCase #PB_OS_Windows
    SetWindowCallback(@WindowCallback(), 0)
CompilerEndSelect

SetActiveGadget(#Text)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      CompilerSelect #PB_Compiler_OS
        CompilerCase #PB_OS_Linux
          gdk_event_handler_set_(0, 0, 0)
        CompilerCase #PB_OS_MacOS
          CFRelease_(MachPort)
      CompilerEndSelect
      Break
    Case #Event_ResizeText
      Select EventType()
        Case #EventType_MouseWheel_Down
          If CurrentFont > 0
            CurrentFont - 1
            SetGadgetFont(0, FontID(CurrentFont))
          EndIf 
        Case #EventType_MouseWheel_Up
          If CurrentFont < #MaxFontID
            CurrentFont + 1
            SetGadgetFont(0, FontID(CurrentFont))
          EndIf 
    EndSelect
  EndSelect
ForEver
Antworten