Page 1 of 1

How to determine if a window is open?

Posted: Sat Oct 26, 2024 8:27 am
by simkot
How to determine if a window is open? For example, Notepad?
As I understand it, you need to use Result = IsWindow(#Window).
But what to substitute as #Window?

Re: How to determine if a window is open?

Posted: Sat Oct 26, 2024 9:15 am
by infratec
PB can only detect own windows.

You need windows API commands.
You need to EnumWindows and then IsWindowVisible.
If it is visioble you can check the title.

Re: How to determine if a window is open?

Posted: Sat Oct 26, 2024 9:25 am
by infratec

Code: Select all

EnableExplicit

Structure EnumWindow_Structure
  TitlePart$
  hWnd.i
EndStructure


Procedure.i EnumWindowsCallback(hWnd.i, *lParam.EnumWindow_Structure)
  
  Protected *Buffer, Title$, Result
  
  
  Result = #True
  If IsWindowVisible_(hWnd)
    *Buffer = AllocateMemory(1024)
    If *Buffer
      If GetWindowText_(hWnd, *Buffer, MemorySize(*Buffer))
        Title$ = PeekS(*Buffer)
        If Title$ <> ""
          Debug Title$ + " (" + Str(hWnd) + ")"
          If *lParam <> #Null
            If *lParam\TitlePart$ <> ""
              If FindString(Title$, *lparam\TitlePart$)
                *lParam\hWnd = hWnd
                Result = #False
              EndIf
            EndIf
          EndIf
        EndIf
      EndIf
      FreeMemory(*Buffer)
    EndIf
  EndIf
  
  ProcedureReturn Result
  
EndProcedure




Procedure.i FindVisibleWindowByTitlePart(TitlePart$)
  
  Protected EnumWindow.EnumWindow_Structure
  
  
  EnumWindow\hWnd = 0
  EnumWindow\TitlePart$ = TitlePart$
  
  EnumWindows_(@EnumWindowsCallback(), @EnumWindow)
  
  ProcedureReturn EnumWindow\hWnd
  
EndProcedure





#KEYEVENTF_UNICODE = 4

Procedure.i SendString (s$)
   ; -- sends a Unicode string to the foreground window
   ; in : s$: Unicode-String (may contain characters outside of the BMP)
   ; out: number of events that were successfully inserted into the input stream
   ;
   ; <https://stackoverflow.com/questions/50420514/sendinput-wont-send-basic-unicode-to-some-windows>
   Protected.Character *char, *char2
   Protected.i i=0, nEvents=2*Len(s$)
   
   If OSVersion() < #PB_OS_Windows_2000 Or nEvents = 0
      ProcedureReturn 0
   EndIf
   
   Protected Dim send.Input(nEvents-1)
   *char = @s$
   
   While *char\c <> 0
      If *char\c < $D800 Or *char\c > $DFFF
         send(i)\type = #INPUT_KEYBOARD
         send(i)\ki\wVk = 0
         send(i)\ki\wScan = *char\c
         send(i)\ki\dwFlags = #KEYEVENTF_UNICODE
         i + 1
         
         send(i)\type = #INPUT_KEYBOARD
         send(i)\ki\wVk = 0
         send(i)\ki\wScan = *char\c
         send(i)\ki\dwFlags = #KEYEVENTF_UNICODE | #KEYEVENTF_KEYUP
         i + 1
         
      Else
         *char2 = *char + SizeOf(Character)
         
         send(i)\type = #INPUT_KEYBOARD
         send(i)\ki\wVk = 0
         send(i)\ki\wScan = *char\c
         send(i)\ki\dwFlags = #KEYEVENTF_UNICODE
         i + 1
         
         send(i)\type = #INPUT_KEYBOARD
         send(i)\ki\wVk = 0
         send(i)\ki\wScan = *char2\c
         send(i)\ki\dwFlags = #KEYEVENTF_UNICODE
         i + 1
         
         send(i)\type = #INPUT_KEYBOARD
         send(i)\ki\wVk = 0
         send(i)\ki\wScan = *char\c
         send(i)\ki\dwFlags = #KEYEVENTF_UNICODE | #KEYEVENTF_KEYUP
         i + 1
         
         send(i)\type = #INPUT_KEYBOARD
         send(i)\ki\wVk = 0
         send(i)\ki\wScan = *char2\c
         send(i)\ki\dwFlags = #KEYEVENTF_UNICODE | #KEYEVENTF_KEYUP
         i + 1
         
         *char = *char2
      EndIf
      
      *char + SizeOf(Character)
   Wend
   
   ProcedureReturn SendInput_(nEvents, @send(), SizeOf(Input))
   
EndProcedure




Define Title$, hWnd.i


Title$ = "Unbenannt - Editor"
;hWnd = FindWindow_(#Null, Title$)
hWnd = FindVisibleWindowByTitlePart("Editor")
If hWnd
  If IsWindowVisible_(hWnd)
    Debug Title$ + " is open"
    SetForegroundWindow_(hWnd)
    ShowWindow_(hWnd, #SW_MAXIMIZE)
    SendString(#LF$ + "Hello from PureBasic" + #LF$)
  EndIf
EndIf
FindWindow_() needs the exact title of the window.
With the enumeration you can use FindString() to detect a substring.

Re: How to determine if a window is open?

Posted: Sat Oct 26, 2024 12:06 pm
by simkot
Thank you! Can I then control this window? Make it active, expand it to full screen or minimize it? Can I send it a keyboard command? For example, Enter or Ctrl+V?

Re: How to determine if a window is open?

Posted: Sat Oct 26, 2024 12:24 pm
by infratec
I updated the code above and used a Procedure from Little John for the key sending.
viewtopic.php?p=628747

But ...
you are the programmer. Sarch for ways and implement them. :wink:
If you run in problems, ask.

And ... if you run it once it will not work agan with notepad, because the title is changing (the unsaved mark * is added.)

Re: How to determine if a window is open?

Posted: Sat Oct 26, 2024 4:30 pm
by infratec
Changed the listing above to find a window by a part of the title.

Now you can run it multible times with the Editor (Notepad) :wink:

Re: How to determine if a window is open?

Posted: Sat Oct 26, 2024 4:52 pm
by AZJIO

Re: How to determine if a window is open?

Posted: Sat Oct 26, 2024 4:59 pm
by Axolotl
On Windows Notepad 11.2302.16.0 this works for me.....
Problem: the new Win UI stuff doesn't work like it used to. :oops:

Code: Select all

EnableExplicit 

Procedure EnumFunc(hwnd, LParam) 
  Protected cn${#MAX_PATH} 

  If GetClassName_(hwnd, @cn$, #MAX_PATH) And cn$ = "RichEditD2DPT" 
    PokeI(LParam, hwnd)   ; copy return value --> found richedit control handle 
    ProcedureReturn #False  ; done with enumeration 
  EndIf 
  ProcedureReturn #True   ; continue enumeration 
EndProcedure 

; ---------------------------------------------------------------------------------------------------------------------

Procedure SendToNotepad(Message$) 
  Protected hwndNotepad, hwnd 
  
  hwndNotepad = FindWindow_(@"Notepad", 0) 
  If hwndNotepad                                          : Debug " Notepad = " + hwndNotepad
    EnumChildWindows_(hwndNotepad, @EnumFunc(), @hwnd) 

    If hwnd <> 0                                          : Debug "RichEdit = " + hwnd 
      SendMessage_(hWnd, #EM_SETSEL, $fffffff, $fffffff)        ; no selection, caret at the end 
      SendMessage_(hWnd, #EM_REPLACESEL, 0, Message$)           ; no  #CRLF$ by default 
    EndIf 
  EndIf 
EndProcedure 

; ---------------------------------------------------------------------------------------------------------------------

Procedure Main() 

; RunProgram("notepad.exe")  ; open a new one 
; Delay(200) 	; the machine needs some time to create the stuff 

  SendToNotepad(#CRLF$ + "=== " + FormatDate("%dd.%mm.%yyyy %hh:%ii", Date()) + LSet(" ", 59, "=") + #CRLF$ + #CRLF$) 

EndProcedure 

End Main()