Hi!

We use a programm called X-Win32 ( www.starnet.com ) for visualization of Unix programms.
My problem is, that all created Windows have different captions and the same Classname ("XWinClass"). And they are created at the same time (almost ;) ). I need to get the handle of each Window to remove the WS_CAPTION style ("and eax, not WS_CAPTION" :) ), move the window and resize it.
My idea was just to run FindWindow with "XWinClass" as Classname, save the handle in an array, change the class to something else (like "XWinClassDone") and start over with FindWindow again.

If anyone has another suggestion how to save the handles, please reply. GetTopWindow / GetNextWindow is no option, because there are some other apps running which get the focus with each refresh and might intercept a GetTopWindow call :/

Thanks,
bazik
Posted on 2002-09-16 08:05:53 by bazik
my guess would be: SetClassLong,hWnd,36,ptr_classname according to the api
ref it should work... but if this is not the case then try to set the windows pos to
HWND_BOTTOM...

...


WNDCLASSEX STRUCT
cbSize DWORD ? 0
style DWORD ? 4
lpfnWndProc DWORD ? 8
cbClsExtra DWORD ? 12
cbWndExtra DWORD ? 16
hInstance DWORD ? 20
hIcon DWORD ? 24
hCursor DWORD ? 28
hbrBackground DWORD ? 32
lpszMenuName DWORD ? 34
lpszClassName DWORD ? 36
hIconSm DWORD ? 40
WNDCLASSEX ENDS

...
but i doubt that you can simply pass a pointer to a string that is stored in YOUR
process, so just grab a debugger and search for some decent string values in that
program you are talking about. or just use hInstance :D
Posted on 2002-09-16 08:15:54 by mob
Hi mob,
thanks for your reply but unfortunately it doesn't work and this newsgroup post verifies it :/
Posted on 2002-09-16 08:27:01 by bazik

but SetClassLong doesn't allow me to change the name



but i doubt that you can simply pass a pointer to a string that is stored in YOUR
process, so just grab a debugger and search for some decent string values in that
program you are talking about. or just use hInstance :D


it's clear as daylight that SetClassLong doesn't work when you provide pointers
that are only valid for YOUR process... but when you give it a valid value... it could
be worth a try i think...

other possibility would be to enumerate processes, you know the exe-filename, thats
all you need...
Posted on 2002-09-16 08:32:46 by mob
Cheater!! You edited your post while I was writing my reply! :grin:


And for enumerating... I have one process for ~20 Windows. How should this work? :rolleyes:
Posted on 2002-09-16 08:37:52 by bazik
just in case you didn't solved your problem... it's strange but i had to do
exactly the same yesterday... and... i solved it with the EnumWindows API
which i never used before... here's vb code for ya :grin:


Private Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Public Function fEnumWindowsCallBack(ByVal hWnd As Long, ByVal lpData As Long) As Long
On Error Resume Next

Dim lResult As Long
Dim lThreadId As Long
Dim lProcessId As Long
Dim sWndName As String
Dim sClassName As String

Dim menu_handle As Long
Dim submenu_handle As Long
Dim item_index As Long
Dim result As String
Dim found As String

fEnumWindowsCallBack = 1
sClassName = Space(260)
sWndName = Space(260)
result = Space(260)

lResult = GetClassName(hWnd, sClassName, 260)
sClassName = Left(sClassName, lResult)
lResult = GetWindowText(hWnd, sWndName, 260)
sWndName = Left(sWndName, lResult)

IF sClassName = "XWinClass" THEN

'hWnd -> handle
'sClassName -> ...
'sWndName -> window title

END IF

End Function

Public Function fEnumWindows() As Boolean
Dim hWnd As Long
Call EnumWindows(AddressOf fEnumWindowsCallBack, hWnd)
End Function

oh, in vb this must be thrown in an extra module... then you just have to
call fEnumWindows... in asm this would be more than easy...
Posted on 2002-09-19 05:58:43 by mob
Yep, I solved it right after your last reply. Here is my PowerBASIC source :)



#COMPILE DLL 'EXE
#INCLUDE "win32api.inc"

GLOBAL g_nHwnd AS LONG
GLOBAL g_nProcessID AS LONG

FUNCTION EnumWindowsProc(BYVAL nHwnd AS LONG, BYVAL nParam AS LONG) AS LONG

DIM nProcessID AS LONG
'DIM nThreadID AS LONG
'DIM szBuffer AS ASCIIZ * 512

CALL GetWindowThreadProcessId(nHwnd, nProcessID)

'CALL GetWindowText(nHwnd, szBuffer, 512)
'MSGBOX "szBuffer: " + szBuffer + $CRLF _
' + "nThreadID: " + STR$(nThreadID) + $CRLF _
' + "nProcessID: " + STR$(nProcessID) + $CRLF _
' + "nParam: " + STR$(g_nProcessID)

IF nProcessID = g_nProcessID THEN

' MSGBOX "nProcessID: " + STR$(nProcessID) + CHR$(13,10) + "nParam: " + STR$(g_nProcessID)

'OPEN "test.txt" FOR APPEND AS #1
' PRINT #1, STR$(nProcessID) + ", " + szBuffer
'CLOSE #1
g_nHwnd = nHwnd
EnumWindowsProc = 0
ELSE
EnumWindowsProc = 1
END IF

END FUNCTION

FUNCTION WindowHandleFromProcessId(BYVAL nProcessID AS LONG) EXPORT AS LONG
'MSGBOX "nProcessID (VB): " + STR$(nProcessID)
g_nProcessID = nProcessID
CALL EnumWindows(CODEPTR(EnumWindowsProc), 0)
'MSGBOX "g_nHwnd: " + STR$(g_nHwnd)
FUNCTION = g_nHwnd
'MSGBOX "done"

END FUNCTION
Posted on 2002-09-19 06:16:59 by bazik
And because we are all 1337 VB coders, here is the sub which calls this PowerBASIC library... :grin:



Private Sub cmdOpen_Click()

Dim sLine As String
Dim sBuffer As String * 512

Dim vLine As Variant
Dim vGroup As Variant

Dim n As Long

Dim nStyle As Long
Dim nHandle As Long
Dim nRet As Long
Dim nProcess As Long

Dim pi As PROCESS_INFORMATION
Dim si As STARTUPINFO

g_CurrentX = 0
g_CurrentY = 0

Open g_sScriptFile For Input As #1

Do Until EOF(1)
Line Input #1, sLine

If Left$(sLine, 1) <> "#" And Len(sLine) > 0 Then

vLine = Split(sLine, "|")
' MsgBox UBound(vLine)
If UBound(vLine) = 4 Then
' 0 :: Befehl
' 1 :: Parameter
' 2 :: Arbeitsverzeichniss
' 3 :: Gruppe(n)
' 4 :: Kommando Datei

vGroup = Split(vLine(3), ",")

For n = 0 To UBound(vGroup)
If vGroup(n) = cmb1.ListIndex Then

si.cb = Len(si)
' MsgBox vLine(0) + vbCrLf + vLine(1)
nRet = CreateProcess(0, vLine(0) + " " + vLine(1), ByVal 0&, ByVal 0&, 1&, _
NORMAL_PRIORITY_CLASS, ByVal 0&, vLine(2), si, pi)
If nRet = 0 Then
MsgBox "Fehler bei Prozesserstellung:" + vbCrLf + vLine(0) + " " + vLine(1), vbCritical, "Fehler!"
Exit Sub
End If

Call WaitForInputIdle(pi.hProcess, INFINITE)


' Call EnumWindows(AddressOf EnumWindowsProc, sei.hProcess)
' MsgBox "test2"
' MsgBox "pi.dwProcessId: " + Str$(pi.dwProcessId)

g_nProcessList(g_nProcessCount) = pi.hProcess

If InStr(vLine(0), "xwin32") <> 0 Then
lblLoop:
Do
nHandle = FindWindow("XWinClass", 0)
DoEvents
' Debug.Print nHandle
Loop Until nHandle <> 0

nRet = GetWindowText(nHandle, sBuffer, 512)
sBuffer = Left$(sBuffer, nRet)

If Trim(sBuffer) = "X-Root" Then
GoTo lblLoop
End If

Call SetWindowText(nHandle, "X-Root")

' Call GetWindowThreadProcessId(nHandle, nProcess)
' MsgBox nProcess
' g_nProcessList(g_nProcessCount) = nProcess

g_nHandleList(g_nProcessCount) = nHandle

ElseIf InStr(vLine(1), "telnet") <> 0 Then
lblLoop2:
Do
nHandle = FindWindow("ConsoleWindowClass", 0)
DoEvents
Loop Until nHandle <> 0

nRet = GetWindowText(nHandle, sBuffer, 512)
sBuffer = Left$(sBuffer, nRet)

' MsgBox Trim(sBuffer)

If Trim(sBuffer) = "Telnet-Session" Then
GoTo lblLoop2
End If

Call SetWindowText(nHandle, "Telnet-Session")

g_nHandleList(g_nProcessCount) = nHandle

Else
[b]g_nHandleList(g_nProcessCount) = WindowHandleFromProcessId(pi.dwProcessId)[/b]
End If
' MsgBox "nHandleList: " + Str$(nHandleList(nProcessCount))
' MsgBox nHandleList(nProcessCount)

' MsgBox g_nProcessCount

'nStyle = GetWindowLong(g_nHandleList(g_nProcessCount), GWL_STYLE)

'nStyle = nStyle And Not WS_CAPTION

'Call SetWindowLong(g_nHandleList(g_nProcessCount), GWL_STYLE, nStyle)

If vLine(4) <> "0" Then
Sleep 2000
SendKeys vLine(4), True
End If

'If (g_CurrentX <= g_ScreenWidth) And _
' ((g_CurrentX + Val(vLine(3))) <= g_ScreenWidth) Then

' Call MoveWindow(g_nHandleList(g_nProcessCount), g_CurrentX, _
g_CurrentY, Val(vLine(3)), Val(vLine(4)), 1)
' g_CurrentX = g_CurrentX + Val(vLine(3))

'Else
' g_CurrentX = 0

' g_CurrentY = Val(vLine(6)) ' g_CurrentY + 300

' Call MoveWindow(g_nHandleList(g_nProcessCount), g_CurrentX, _
g_CurrentY, Val(vLine(3)), Val(vLine(4)), 1)
' g_CurrentX = g_CurrentX + Val(vLine(3))

'End If
g_nProcessCount = g_nProcessCount + 1
' MsgBox sei.hProcess


End If
Next n

Else

MsgBox "Fehler in Datei " + Chr(34) + _
g_sScriptFile + Chr(34) + vbCrLf + _
sLine + vbCrLf + "Zu wenig Datenfelder!", _
vbCritical, "Fehler!"
Exit Sub
End If

End If
Loop

Call TileWindows(0, MDITILE_HORIZONTAL, ByVal 0&, g_nProcessCount, g_nHandleList(0))

Close #1

End Sub
Posted on 2002-09-19 06:20:15 by bazik
one last thing...

what i think is very funny is that those stupid vb coders compare dull api's with the
holly grail or something like that haha even after years and years of experience...
companys only engage these dumb know-nothing vb students to save costs. that
is so terrible, no wonder that this industrial sector is dying in germany.
Posted on 2002-09-19 06:38:45 by mob
Everytime I tell a VB'er that BASIC is an acronym and that the B stands for "Beginner" they don't believe me.

Then once I prove it to them they look so hurt. As if the truth had just stabbed them through the heart. Poor VBers. /pat /pat
Posted on 2002-09-19 13:05:53 by iblis