How to determine if a window is open?

Just starting out? Need help? Post your questions and find answers here.
simkot
User
User
Posts: 31
Joined: Sat Oct 26, 2024 8:25 am

How to determine if a window is open?

Post 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?
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: How to determine if a window is open?

Post 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.
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: How to determine if a window is open?

Post 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.
Last edited by infratec on Sat Oct 26, 2024 4:29 pm, edited 2 times in total.
simkot
User
User
Posts: 31
Joined: Sat Oct 26, 2024 8:25 am

Re: How to determine if a window is open?

Post 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?
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: How to determine if a window is open?

Post 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.)
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: How to determine if a window is open?

Post 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:
AZJIO
Addict
Addict
Posts: 2225
Joined: Sun May 14, 2017 1:48 am

Re: How to determine if a window is open?

Post by AZJIO »

Axolotl
Addict
Addict
Posts: 872
Joined: Wed Dec 31, 2008 3:36 pm

Re: How to determine if a window is open?

Post 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() 
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
Post Reply