Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

Hey I'm gonna try to be as clear as possible

 

I have an application running called Soldier of Fortune 2 Console.

 

screenshot:

http://boeze.com/~ontani2/ssa/sofserver.jpg

 

I send messages to this window with a VB.NET application.

this works perfect, i use this code:

 

Dim hwnd As Integer = FindWindow(vbNullString, "Soldier of Fortune 2 Console")
Dim x As Integer = FindWindowEx(hwnd, 0, "Edit", vbNullString)
Dim strText As String = "/status"
If Not x = 0 Then
   SendMessage(x, WM_SETTEXT, 256, strText)
   SendMessage(x, WM_CHAR, 13, 1835009)
End If

 

this sends the command /status to the little textfield of the server window.

 

This command generates who is playing on the server and shows his

id, name, ip, port, etc... in the green textbox.

 

I want to grab this text from the green textbox and put it in a variable.

i tried to use WM_GETMESSAGE but couldn't get it to work.

 

screenshot:

http://boeze.com/~ontani2/ssa/sofserverhandles.jpg

 

shows the information from the window i got from Spy++

 

Can someone help me with this problem?

 

Greetz From Ontani

Posted (edited)

solution

 

The only way I know of is to use SendMessage with WM_GETTEXT not WM_GETMESSAGE.

 

I'm not sure of the VB code for it but...

 

1. Find the correct window

2. Use WM_GETTEXTLENGTH to find how much text is there.

3. Create a new string with the returned value from WM_GETTEXTLENGTH + 1 of spaces. Add 1 space as shown for End of String deliminator.

4. Use SendMessage and pass it the reference of the string you created using WM_GETTEXT.

5. Your string now contains the text of the window. You can Trim any excess whitespace, etc afterwords.

Edited by coldfusion244
-Sean
Posted

ok i searched around for the WM_GETTEXT and WM_GETTEXTLENGHT Thingy

 

   Private Declare Ansi Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
   Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
   Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As Int32, ByVal hWnd2 As Int32, ByVal lpsz1 As String, ByVal lpsz2 As String) As Int32
   Private Const WM_GETTEXT As Short = &HDS
   Private Const WM_GETTEXTLENGTH As Short = &HES
   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Dim hwnd As Integer = FindWindow(vbNullString, "Soldier of Fortune 2 Console")
       Dim x As Integer = FindWindowEx(hwnd, 0, "Edit", "")
       Dim txtLength As Long = SendMessage(x, WM_GETTEXTLENGTH, CInt(0), CInt(0)) + 1
       Dim txtBuff As String = Space(txtLength)
       Dim TEMP As Long = TEMP = SendMessage(x, WM_GETTEXT, txtLength, txtBuff)
       MessageBox.show(txtBuff)
   End Sub

 

This is what i came up with, and i got in the messagebox the value of the text in the little textfield.

 

but how do i force this to get the value from the large green field?

 

Greetz (Thanx For Your Help Btw)

Posted

First off, you only have the handle of the Edit window which is the textbox you enter "/status". You need the handle of the window that has the information in it. Since I don't have this program I am not sure what type of control it is. But you would find it the same way you found the edit textbox.

 

After you find it, you can use the code you had before...

 

Dim txtLength As Long = SendMessage(x, WM_GETTEXTLENGTH, CInt(0), CInt(0)) + 1
Dim txtBuff As String = Space(txtLength)
Dim TEMP As Long = TEMP = SendMessage(x, WM_GETTEXT, txtLength, txtBuff)
MessageBox.show(txtBuff)

 

The only problem with the code you currently have is that x is the handle of the (aforementioned) Edit control that corresponds to the input textbox. So find the handle of the other control and use that as the hWnd arguement.

-Sean
Posted
The other control also calls Edit thats to problem.

 

FindWindowEx can cycle through controls, so my suggestion would be to use Spy++ to find out the handle of the control. Then cycle through the "Edit" controls until you find the correct handle. Then you know it's the xth edit control and you can then find it everytime with FindWindowEx

-Sean
Posted (edited)

I have done exactly what you want to do. The trick is to use the 'EnumChildWindows' API.

 

I used 'EnumWindows' to get the main window hWnd, then once you have that, use 'EnumChildWindows' and specify the main window hWnd, and it will enumerate through all the child controls.

 

Let me know if you can do it from that info. If not, I can post an example.

Edited by sgt_pinky
Posted
FindWindowEx can cycle through controls' date=' so my suggestion would be to use Spy++ to find out the handle of the control. Then cycle through the "Edit" controls until you find the correct handle. Then you know it's the xth edit control and you can then find it everytime with FindWindowEx[/quote']

 

you know how to do this?

i have no idea

Posted

You could also take Pinky's idea and use EnumChildWindows, but I don't think you would have to go through all that right here. Unfortunately as I said above I can't write the code for you because I don't have that particular application...http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/findwindowex.asp

 

Put the handle of the first window as the ChildAfter arguement so that it searches for the next child in the Z-order. I have the link to it above...

 

Hope this helps...

-Sean
Posted

WHOOOP WHOOOP

:) thanx for the ChildAfter argument suggestion that did the trick

 

for those who want the code ...

 

   Private Declare Ansi Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
   Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
   Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As Int32, ByVal hWnd2 As Int32, ByVal lpsz1 As String, ByVal lpsz2 As String) As Int32
   Private Const WM_GETTEXT As Short = &HDS
   Private Const WM_GETTEXTLENGTH As Short = &HES
   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       Dim hwnd As Integer = FindWindow(vbNullString, "Soldier of Fortune 2 Test Console")
       Dim x As Integer = FindWindowEx(hwnd, 0, "Edit", "")
       Dim x2 As Integer = FindWindowEx(hwnd, x, "Edit", "")
       Dim txtLength As Long = SendMessage(x2, WM_GETTEXTLENGTH, CInt(0), CInt(0)) + 1
       Dim txtBuff As String = Space(txtLength)
       Dim TEMP As Long = TEMP = SendMessage(x2, WM_GETTEXT, txtLength, txtBuff)
       MessageBox.Show(txtBuff)
   End Sub

 

Thanx Guys

Posted

Well, thats neater than my version anyway ;) Gets rid of the need to declare a delegate callback function for starters.

 

In fact...I think I might just copy it.... :D

 

Good one.

 

Pinky

Posted
Well, thats neater than my version anyway ;) Gets rid of the need to declare a delegate callback function for starters.

 

In fact...I think I might just copy it.... :D

 

Good one.

 

Pinky

 

Yeah pinky, your way is much Better code because it wouldn't matter if an update came out or such and changed the Z-order. But for simplicity and simple code sake FindWindowEx works nicely :D

-Sean
Posted

It all works like a charm now i want to go a little further offcourse :)

 

i got a buffer string which contains the last rule entered into the window.

 

for example it contains:

 

Kill: 0 2 1: Player 1 killed Player 2 by MOD_KNIFE

 

how do i extract the bold parts.

 

so my program has in 3 string or in an array: Player 1, Player 2, MOD_KNIFE

 

i tried splitting on space but offcourse this wont work if the player has a space in his name.

 

Thanx In Advance

Posted (edited)

You could use String.IndexOf and String.Substring methods.

 

eg:

 

Dim sBlah as string = "aaa killed bbb"
Dim sPlayer1 as string = sBlah.Substring(0,sBlah.IndexOf("killed"))
Dim sPlayer2 as string = sBlah.Substring(sBlah.IndexOf("killed") + "killed".Length,sBlah.Length - (sBlah.IndexOf("killed") + "killed".Length) - 1)

 

Thats how I usually do it. Note that I didnt test this code, the indices and lengths are probably wrong :D

 

Edit: I just had a closer look at your output, and it seems to me that the console displays fixed length format lines anyway, so you can just use the String.SubString method straight away, without searching for the start index of any strings.

Edited by sgt_pinky
Posted

thanx there we go

 

Dim sPlayer1 As String = killed.Substring(0, killed.IndexOf("killed"))
Dim sPlayer2 As String = killed.Substring(killed.IndexOf("killed") + 6, killed.Length - (killed.IndexOf("killed") + 6))

 

variable killed contains: player1 killed player2

Posted

ok there we go. A little step further ;)

 

i got in an array for example this:

 

 5     0   62 -SSF- {+)MC(+}w-up      0 82.149.16.99:20100    60468 10000
 4     0   69 Zereaba W-Up         50 80.2.220.91:2847      60702  5000
 3     9   82 -=TS=-TiTaNiUm*]HoNoR[*      0 81.197.40.212:20100   37750  2500
 2     0   50 ~*NijnTje*~ StyL3 *W-up      0 81.59.180.89:20100    64290  2500
 1     0  143 -SSF- ']['r!gg3r [oLd-SkOoL]      0 172.174.119.140:20100 19296 10000
 0     9   48 ~*Nijntje*~Chill*L      0 81.205.107.2:12600    24627  2500

 

every new line is in a new array index.

 

i want to put in a string the first number for example:5 and the name

-SSF- {+)MC(+}w-up

 

the first numbers is allways 1 digit

but the 2nd can variate.

and the 3th number is variable from 0 till 999

 

well the first number wasn't so much of a deal that did i get by

 

Dim id As String = Mid(aString(aString(i), 3, 1)

 

someone and idea?

 

Greetz

Posted

ok now i created a txt file that contains messages that should be send when some on enters a command.

 

the file looks like this:

"^1Hold ^vYour ^1Fire ^b" & name & " ^vIs Out Of ^1AMMO"
"^1WAIT!, ^b" & name & " ^vNeeds ^1AMMO"
"^vDon'T Shoot ^b" & name & " ^vIs Out Of ^1AMMO"
"^1WAIT!, ^vLet ^b" & name & " ^vGet ^1AMMO"
"^1WOW ^vNice ^1Headshot " & name
"^vWhat An Awsome ^1Headshot ^vBy ^b" & name
"^b" & name & " ^vGive Ya A ^1Headjob"
"^b" & name & " ^vWaves Your Head, ^1ByeBye"
"^1Hey! ^vHaven't Your Parents Learned Ya How To ^1WALK"
"^1Hey Dude! ^vStart ^1Walking ^vFor A Change"
"^vCome On, ^1WALK!"
"^vWhy Don't You Hide This Time? ^1WALK!"
"^1Neckshot ^vBy ^b" & name
"^11mm ^vUnder Your Head But Still A ^1Neckshot"
"^1WOW ^vNice ^1Neckshot ^b" & name
"^vAn Awsome ^1Neckshot ^vBy ^b" & name
"^vDon't Touch Yourself ^1There"
"^b" & name & " ^vRemoved A ^1Ball"
"^b" & name & " ^vMade You Grab Your ^1Balls"
"^vDoctor ^b" & name & " ^vIs Here, He Removed Your ^1Balls"
"^vNice ^b" & name & " ^vYou Killed ^b" & name2
"^b" & name2 & "^v Got Fragged By ^b" & name
"^TNice! ^b" & name
"^vA Pitty For ^b" & name2

 

my code to put those lines into an array is this:

       Dim i, j As Integer
       Dim strNameFile As String = "Messages.txt"
       Dim intNr As Integer
       intNr = FreeFile()
       FileOpen(intNr, strNameFile, OpenMode.Input)

       Do
           For i = 0 To 5
               For j = 0 To 3
                   aMessages(i, j) = LineInput(intNr)
               Next
           Next
       Loop Until EOF(intNr)
       FileClose(intNr)

 

this places the first 4 lines into :

aMessages(0,0), aMessages(0,1), aMessages(0,2), aMessages(0,3)

the next 4 into:

aMessages(1,0), aMessages(1,1), aMessages(1,2), aMessages(1,3)

 

and so on.

 

but the problem is when i send these messages to the server window

the variable name and name2 haven't been replaced like it should.

 

how can i do this?

 

the complete function looks like this:

   Public Function getMessage(ByVal type As String, ByVal name As String, ByVal name2 As String) As String
       Dim i, j As Integer
       Dim strNameFile As String = "Messages.txt"
       Dim intNr As Integer
       intNr = FreeFile()
       FileOpen(intNr, strNameFile, OpenMode.Input)

       Do
           For i = 0 To 5
               For j = 0 To 3
                   aMessages(i, j) = LineInput(intNr)
               Next
           Next
       Loop Until EOF(intNr)
       FileClose(intNr)
       Debug.WriteLine(aMessages(0, 1))
       Select Case type
           Case "ammo"
               Return aMessages(0, RandomId.Next(4))
           Case "hs"
               Return aMessages(1, RandomId.Next(4))
           Case "walk"
               Return aMessages(2, RandomId.Next(4))
           Case "ns"
               Return aMessages(3, RandomId.Next(4))
           Case "bs"
               Return aMessages(4, RandomId.Next(4))
           Case "kill"
               Return aMessages(5, RandomId.Next(4))
       End Select
   End Function

 

greetz

Posted

such a long question and such an easy answer LOL

 

       Dim i, j As Integer
       Dim strNameFile As String = "Messages.txt"
       Dim intNr As Integer
       intNr = FreeFile()
       FileOpen(intNr, strNameFile, OpenMode.Input)

       Do
           For i = 0 To 5
               For j = 0 To 3
                   aMessages(i, j) = LineInput(intNr)
                   aMessages(i, j) = aMessages(i, j).Replace(Chr(34), "")
                   aMessages(i, j) = aMessages(i, j).Replace(" & ", "")
                   aMessages(i, j) = aMessages(i, j).Replace("name2", Mid(name2, 2, name2.Length - 1))
                   aMessages(i, j) = aMessages(i, j).Replace("name", name)
               Next
           Next
       Loop Until EOF(intNr)
       FileClose(intNr)

 

did the trick. Damn why i'm even asking? ;)

Posted

ok next Question :).

 

i got from UDP socket this into a string:

 

5 91 "<*|LoD|*> C.Thunder [sniper]"
0 56 "need clan//-=bibbe=-"
5 48 "-=[F-warz]=- Gnar-Kill [pro-snp"
0 54 "*Dpk* Kruimel (Ldr)"
5 92 "<S|S> Freekill *Co-Ldr*Mp3"

 

the problem is how the hell can i split these.

 

       Dim udp As New UdpClient("127.0.0.1", 20102)
       Dim b() As Byte = System.Text.Encoding.Default.GetBytes("ÿÿÿÿgetstatus")
       udp.Send(b, b.Length)
       Dim thisIP As New System.Net.IPEndPoint(IPAddress.Parse("127.0.0.1"), 0)
       Dim r() As Byte = udp.Receive(thisIP)
       Dim allInfo As String = System.Text.ASCIIEncoding.Default.GetString(r)

 

so allInfo contains that information. i tried:

 

Dim aPlayers() as String = allInfo.Split(VbCrLf)

didn't work!

 

Dim aPlayers() as String = allInfo.Split(VbNewline)

didn't work!

 

Dim aPlayers() as String = allInfo.Split("\n")

didn't work!

 

what is there more?

 

Greetz

Posted

Major problem i used.

 

TabPage1.SendToBack()

TabPage2.SendToBack()

TabPage3.SendToBack()

TabPage4.SendToBack()

TabPage5.SendToBack()

TabPage6.SendToBack()

 

In designer they look like they are on place.

 

but when i run and compile there all mixed up. what the hell is going on here

 

In Design its: [Main][Messages 1][Messages 2][Messages 3][Messages 4][Messages 5][Messages 6]

 

when Compiled: [Main][Messages 1][Messages 3][Messages 5][Messages 4][Messages 2]

 

Someone an idea how to fix this

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...