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.

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)

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.
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()