Seite 2 von 2

Re: PopUp Menü

Verfasst: 05.10.2010 20:19
von PureLust
Darie hat geschrieben:Deswegen möchte ich, dass dann mein Programm aufgerufen wird, dass lediglich ein Popupmenü öffnet und dann ein Shortcut an ein bestimmtes Fenster gesendet wird... >_<
Ah, ok ... für sowas isses gedacht. Na dann geht's natürlich auch ganz einfach und auch ohne API:

Code: Alles auswählen

#WinMain            = 0
#Timer_PopUpTimeOut = 0

If OpenWindow(#WinMain, 10, 10, 140, 100, "PopUp", #PB_Window_Invisible) : Else : End : EndIf ;,#PB_Window_Invisible
ButtonGadget(0,10,10,120,30,"Open PopUp")

If CreatePopupMenu(0)
  MenuItem(1, "Cut")
  MenuItem(2, "Copy")
  MenuItem(3, "Paste")
EndIf

DisplayPopupMenu(0, WindowID(#WinMain))
AddWindowTimer(#WinMain,#Timer_PopUpTimeOut,50)

Repeat
	Event = WaitWindowEvent()
	
	Select Event
		Case #PB_Event_Timer
				Quit = #True
		Case #PB_Event_Menu
			Select EventMenu()     
				Case 1 : Debug "Cut"
					; tu dies
				Case 2 : Debug "Copy"
					; tu das
				Case 3 : Debug "Paste"
					; oder mach was ganz anderes
			EndSelect
			Quit = 1
	EndSelect

Until Quit = 1 Or Event = #PB_Event_CloseWindow
Es wird ganz einfach nach dem Schließen des PopUps ein TimeOut-Timer auf 50ms (wert natürlich frei änderbar) gesetzt.
Wenn also bis dahin noch kein #PB_Event_Menu eingetreten ist, wurde kein Menüeintrag angeklickt und das Programm beendet sich dann automatisch.

Grüße, PL.

Re: PopUp Menü

Verfasst: 05.10.2010 22:25
von Darie
Dankeschön natürlich auch an Edel, TS-Soft und PureLust für ihre Hilfe...

Re: PopUp Menü

Verfasst: 06.10.2010 19:17
von Darie
Tut mir leid, dass ich hier nochmal deswegen poste. Ich hab festgestellt, dass mein Programm nicht immer korrekt geschlossen wird, wenn man ausserhalb des Menüs klickt. Leider weiss ich wirklich nicht, wie man das richtig macht, hab mir auch schon den Thread http://forums.purebasic.com/german/view ... 4195bd6211 angeschaut, blicke aber trotzdem nicht durch.

Hier ist mein aktueller Code, ihr müsstet dafür noch eine Textdatei erstellen und die Compileroption "temp. Executable im Quellverzeichnis erstellen" wählen.

hier die Texdatei, bitte als "default.pop" speichern

Code: Alles auswählen

Hallo={Shift}Hallo
String=Dies ist ein Teststring
Schwenken=h
Datum einfügen={F5}
Pinsel=b
Pipette=i
Undo={Alt}{Ctrl}z
---
Bamboo="C:\Program Files\Tablet\Pen\Consumer_CPL.exe"
---
>Submenu
Sub1=Ein Submenü
Sub2=Auch ein Submenü
<

Code: Alles auswählen

Global Quit=0
Global Target.l
Global NewList Commands.s()

#TPM_RETURNCMD = $100

Declare TransmitMessage(num)
Declare SendKeys(handle,window$,keys$)
Declare.s GetExeFromHandle(hWnd.l = 0)
Declare.b ProgramExists(ProgrammName.s)
Declare.s GetWindowText(hwnd)
Declare WinCallback(hWnd, uMsg, wParam, lParam) 
  

Target = GetForegroundWindow_()
If ProgramExists("PopUp") : End : EndIf


GetCursorPos_(@p.point)

If OpenWindow(0, p\x,p\y , 20, 20, "PopUp",#PB_Window_Tool);, #PB_Window_Invisible
 SetWindowLongPtr_(WindowID(0),#GWL_EXSTYLE,GetWindowLongPtr_(WindowID(0),#GWL_EXSTYLE) | #WS_EX_LAYERED)
 SetLayeredWindowAttributes_(WindowID(0), 0, 1, #LWA_ALPHA)
EndIf

;SetWindowCallback(@WinCallback())

Path$ = GetPathPart(GetExeFromHandle(WindowID(0)))
File=ReadFile(#PB_Any, Path$+"default.pop")

If File
 Repeat         
   AddElement(Commands())
   Commands() = ReadString(File)
  Until Eof(File) = 1
  CloseFile(File)               
Else
 MessageRequester("Information","Konnte Datei nicht öffnen!") : End 
EndIf

LastElement(Commands())
DeleteElement(Commands())

CreatePopupMenu(0)
ForEach Commands()
  If Commands() = "---"
   MenuBar() 
 ElseIf Mid(Commands(),1,1) = ">"
   OpenSubMenu(Mid(Commands(),2,Len(Commands())-1))
 ElseIf Mid(Commands(),1,1) = "<"
   CloseSubMenu()
 Else 
   MenuItem(ListIndex(Commands())+1, StringField(Commands(),1,"="))
  EndIf 
Next Commands()

;SetForegroundWindow_(WindowID(0))
;StickyWindow(0,1) 
AddWindowTimer(0,0,50)

Repeat
 
  Event = WaitWindowEvent()
  
  If Event = #PB_Event_Timer : Quit=1 : EndIf
  
  Command = TrackPopupMenu_(MenuID(0), #TPM_RETURNCMD, p\x, p\y, 0, WindowID(0), 0)
  If Command > 0
   TransmitMessage(Command)  
   Quit = 1  
 Else
   Quit = 1   
 EndIf
   
Until Quit = 1 Or Event = #PB_Event_CloseWindow

RemoveWindowTimer(0,0)

End

Procedure WinCallback(hWnd, uMsg, wParam, lParam) 
  
  
    
EndProcedure 

Procedure.s GetExeFromHandle(hWnd.l = 0)
  
  Protected Result.s, PID.l, handle.l, err.l
  Protected Entry.MODULEENTRY32
 
  If hWnd = 0 : hWnd = GetForegroundWindow_() : EndIf
 
  Entry\dwSize = SizeOf(MODULEENTRY32)
  GetWindowThreadProcessId_(hWnd, @PID)
  handle = CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE, PID)

  If handle
    err = Module32First_(handle, Entry)
    If err
       Result = PeekS(@Entry\szExePath)
    EndIf
    CloseHandle_(handle)
  EndIf 
 
  ProcedureReturn Result
EndProcedure

Procedure TransmitMessage(num)
  
  num - 1
  SelectElement(Commands(), num)
  pos = FindString(Commands(), "=", 1)
  If pos <> 0
    Commands() = Mid(Commands(), pos + 1, Len(Commands()))
  EndIf
  
  If Mid(Commands(),1,1) = Chr(34)
   Commands() = Mid(Commands(),2,Len(Commands())-2)
   RunProgram(Commands()) : ProcedureReturn
  EndIf
  
  SendKeys(Target,"",Commands())
 
EndProcedure

Procedure SendKeys(handle,window$,keys$)
  
If window$<>"" : handle=FindWindow_(0,window$) : EndIf ; Use window$ instead of handle.
   If IsWindow_(handle)=0 ; Does the target window actually exist?
      ProcedureReturn 0 ; Nope, so report 0 for failure to type.
   Else
   ; This block gives the target window the focus before typing.
   thread1=GetWindowThreadProcessId_(GetForegroundWindow_(),0)
   thread2=GetWindowThreadProcessId_(handle,0)
   If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
      SetForegroundWindow_(handle) ; Target window now has the focus for typing.
      Delay(125) ; 1/8 second pause before typing, to prevent fast CPU problems.
      ; Now the actual typing starts.
      For r=1 To Len(keys$)
          vk$=Mid(keys$,r,1)
          If vk$="{" ; Special key found.
             s=FindString(keys$,"}",r+1)-(r+1) ; Get length of special key.
             s$=Mid(keys$,r+1,s) ; Get special key name.
             Select s$ ; Get virtual key code of special key.
                Case "ALTDOWN" : keybd_event_(#VK_MENU,0,0,0) ; Hold ALT down.
                Case "Alt" : keybd_event_(#VK_MENU,0,0,0) ; Hold ALT down. 
                Case "ALTUP" : keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT.
                Case "BACKSPACE" : vk=#VK_BACK
                Case "CONTROLDOWN" : keybd_event_(#VK_CONTROL,0,0,0) ; Hold CONTROL down.
                Case "Ctrl" : keybd_event_(#VK_CONTROL,0,0,0) ; Hold CONTROL down
                Case "CONTROLUP" : keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL.
                Case "DELETE" : vk=#VK_DELETE
                Case "DOWN" : vk=#VK_DOWN
                Case "END" : vk=#VK_END
                Case "ENTER" : vk=#VK_RETURN
                Case "T" : vk=#VK_T
                Case "A" : vk=#VK_A
                Case "D" : vk=#VK_D
                Case "X" : vk=#VK_X
                Case "V" : vk=#VK_V
                Case "F1" : vk=#VK_F1
                Case "F2" : vk=#VK_F2
                Case "F3" : vk=#VK_F3
                Case "F4" : vk=#VK_F4
                Case "F5" : vk=#VK_F5
                Case "F6" : vk=#VK_F6
                Case "F7" : vk=#VK_F7
                Case "F8" : vk=#VK_F8
                Case "F9" : vk=#VK_F9
                Case "F10" : vk=#VK_F10
                Case "F11" : vk=#VK_F11
                Case "F12" : vk=#VK_F12
                Case "ESCAPE" : vk=#VK_ESCAPE
                Case "HOME" : vk=#VK_HOME
                Case "INSERT" : vk=#VK_INSERT
                Case "LEFT" : vk=#VK_LEFT
                Case "PAGEDOWN" : vk=#VK_NEXT
                Case "PAGEUP" : vk=#VK_PRIOR
                Case "PRINTSCREEN" : vk=#VK_SNAPSHOT
                Case "RETURN" : vk=#VK_RETURN
                Case "RIGHT" : vk=#VK_RIGHT
                Case "SHIFTDOWN" : shifted=1 : keybd_event_(#VK_SHIFT,0,0,0) ; Hold SHIFT down.
                Case "Shift" : shifted=1 : keybd_event_(#VK_SHIFT,0,0,0) ; Hold SHIFT down.  
                Case "SHIFTUP" : shifted=0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT.
                Case "TAB" : vk=#VK_TAB
                Case "UP" : vk=#VK_UP
             EndSelect
             If Left(s$,3)<>"ALT" And Left(s$,7)<>"CONTROL" And Left(s$,5)<>"SHIFT"
                keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the special key.
             EndIf
             r=r+s+1 ; Continue getting the keystrokes that follow the special key.
          Else
             vk=VkKeyScanEx_(Asc(vk$),GetKeyboardLayout_(0)) ; Normal key found.
             If vk>304 And shifted=0 : keybd_event_(#VK_SHIFT,0,0,0) : EndIf ; Due to shifted character.
             keybd_event_(vk,0,0,0) : keybd_event_(vk,0,#KEYEVENTF_KEYUP,0) ; Press the normal key.
             If vk>304 And shifted=0 : keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) : EndIf ; Due to shifted character.
          EndIf
      Next
      If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#False) : EndIf ; Finished typing to target window!
      keybd_event_(#VK_MENU,0,#KEYEVENTF_KEYUP,0) ; Release ALT key if user forgot.
      keybd_event_(#VK_CONTROL,0,#KEYEVENTF_KEYUP,0) ; Release CONTROL key if user forgot.
      keybd_event_(#VK_SHIFT,0,#KEYEVENTF_KEYUP,0) ; Release SHIFT key if user forgot.
      ProcedureReturn 1 ; Report successful typing! :)
   EndIf
 EndProcedure
 
Procedure.b ProgramExists(ProgrammName.s)
   CreateMutex_(0, 1, ProgrammName)
   If (GetLastError_() = #ERROR_ALREADY_EXISTS)
      ProcedureReturn #True
   Else
      ProcedureReturn #False     
   EndIf
 EndProcedure
 
Procedure.s GetWindowText(hwnd)
  Protected l.l, buffer$
  l = GetWindowTextLength_(hwnd)+1
  buffer$ = Space(l)
  If GetWindowText_(hwnd, buffer$, l)
    ProcedureReturn buffer$
  EndIf
EndProcedure
Am besten kann man das Programm auf einem Notepadfenster testen. Leider schliesst sich mein Programm nicht immer zuverlässig.

Alexander

Re: PopUp Menü

Verfasst: 07.10.2010 15:03
von Darie
Mmh, hat niemand eine Idee, was ich noch machen könnte? Sobald das Fenster unsichtbar ist, funktionieren eure Lösungsvorschläge nichtmehr. Es liegt wohl daran, dass der Fokus nach dem Öffnen nichtmehr auf meinem Fenster liegt. Hab schon versucht den Focus wieder neuzusetzen, klappt aber irgendwie auch nicht.


EDIT: Hat sich erledigt. Lösung gefunden...

Re: PopUp Menü

Verfasst: 08.10.2010 14:16
von HeX0R
Darie hat geschrieben: EDIT: Hat sich erledigt. Lösung gefunden...
Cool!
Der nächste, der diesen Thread findet und das selbe Problem hat, freut sich bestimmt über diesen Abschluss... :roll:
ist in Arbeit (bobobo) :)

Re: PopUp Menü

Verfasst: 08.10.2010 23:07
von Darie
Das Problem bei der Sache war, dass mein unsichtbares Fenster öfters mal den Focus verloren hat und das "Quit"-Event dadurch nicht ausgelöst wurde. Hab anfangs versucht mit StickyWindow und ähnlichem den Focus zurückzuholen, dass reicht aber nicht aus. Wenn man den folgenden Code einfügt, erhält das Fenster aufjedenfall den Focus und das Problem ist gelöst:

Code: Alles auswählen

thread1=GetWindowThreadProcessId_(GetForegroundWindow_(),0)
thread2=GetWindowThreadProcessId_(WindowID(0),0)
If thread1<>thread2 : AttachThreadInput_(thread1,thread2,#True) : EndIf
SetForegroundWindow_(WindowID(0)) ; Target window now has the focus for typing.
Delay(125) ; 1/8 second pause before typing, to prevent fast CPU problems.

Re: PopUp Menü

Verfasst: 09.10.2010 11:17
von HeX0R
Ein bisschen viel Api, hätte eine Kombination von StickyWindow() und SetActiveWindow() nicht auch geholfen?

Re: PopUp Menü

Verfasst: 09.10.2010 14:42
von Darie
Leider reicht das nicht aus <)