• Welcome to Valhalla Legends Archive.
 

ListBox inside StarCraft: how to add items to it?

Started by Don Cullen, February 11, 2006, 07:05 PM

Previous topic - Next topic

Don Cullen

So far, this is the code I have (the form has one text area and one button, named as text1 and command1):

---Form1.frm---

Private Sub Command1_Click()
    Dim BW As Long, TXT As Long, SM As Long, CHILD As Long, Stuff As String
    BW = FindWindow("SWarClass", "Brood War") 'Find hwnd of brood war window
    If (BW = 0) Then
        MsgBox "Window not found!"
        Exit Sub
    End If
    CHILD = FindWindow("SDlgDialog", vbNullString) 'find dialog of brood war window
    TXT = FindWindowEx(CHILD, 0, "ListBox", vbNullString) 'find hwnd of the textbox
    Stuff = Text1.text 'add the text to a string
    SendMessage TXT, WM_SETTEXT, 0, ByVal Stuff 'use settext to send the text string to the listbox on brood war
End Sub

---Module1.bas---

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpszClassName As String, ByVal lpszWindow As String) As Long
Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long


The program isn't working though- nothing is added to the chat (listbox) of the StarCraft client. Any idea what I'm doing wrong? Thanks in advance for any assistance rendered.
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

UserLoser

Maybe you should use a Listbox message id instead of a text box window message id.  Try seeing LB_* messages and not WM_* messages... Setting the text of a listbox--what will that set? what text? nothing at all

Don Cullen

from what i can see using Winspector, there are the following:

LBS_HASSTRINGS
LBS_NOSEL
LBS_OWNERDRAWFIXED
LBS_OWNERDRAWVARIABLE
LBS_USETABSTOPS
LBS_WANTKEYBOARDINPUT
LBS_DISABLENOSCROLL
LBS_EXTENDEDSEL
LBS_MULTICOLUMN
LBS_MULTIPLESEL
LBS_NODATA
LBS_NOINTEGRALHEIGHT
LBS_NOREDRAW
LBS_NOTIFY
LBS_OWNERDRAWVARIABLE
LBS_SORT

Using winspector, I saw there were three listboxes (i only see two, which is the chat window and the channel list, so i'm guessing the third one is the friends list?). I had winspector disable/enable viewing for each listbox until i saw the chat disappeared. But I'm not sure as to how to have it target THAT listbox, seeing how there's three of them. Winspector says for that listbox: 003C0412: ListBox. I'm not sure what the numbers/letter mean-- I'm guessing that's the address for the listbox in hex? And how exactly do I add text to the chat listbox? If I sound like a newb, my apologies, I'm just trying my best to understand this. I'm fairly new to hooking/subclassing.

Thanks for your help!
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

MyndFyre

More likely that is the listbox window handle (HWND).
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

Don Cullen

I found the correct command to use to add items to an external listbox, I think. I'm not sure. In any case, I tried putting in the hex address, but that doesn't work. Also everytime i restart SC, the hex address for the chat listbox changes. So that route can't really be done.

I fixed the overflow error thanks to |2-shadow. However the program is far from working-- when I click command1, it sends nothing to the chat. Or to be more accurate, in the chat, the string that was supposed to be displayed wasn't displayed. The chat remained the same.

Here's new code:

form1.frm:
Private Sub Command1_Click()
    Dim BW As Long, TXT As Long, SM As Long, CHILD As Long, Stuff As String
    BW = FindWindow("SWarClass", "Brood War") 'Find hwnd of brood war window
    If (BW = 0) Then
        MsgBox "Window not found!"
        Exit Sub
    End If
    CHILD = FindWindow("SDlgDialog", vbNullString) 'find dialog of brood war window
    TXT = FindWindowEx(CHILD, 0, "ListBox", vbNullString)    'find hwnd of the first listbox then skip
    Stuff = "TEXT YOU WANT TO SEND" 'add the text to a string
    'Send the text string to the chat listbox on brood war
    SendDlgItemMessage TXT, IDC_LIST, LB_ADDSTRING, 0, ByVal Stuff
End Sub


module1.bas:
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpszClassName As String, ByVal lpszWindow As String) As Long
Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Any) As Long

' Listbox Notification Codes
Public Const LBN_ERRSPACE = (-2)
Public Const LBN_SELCHANGE = 1
Public Const LBN_DBLCLK = 2
Public Const LBN_SELCANCEL = 3
Public Const LBN_SETFOCUS = 4
Public Const LBN_KILLFOCUS = 5

' Listbox messages
Public Const LB_ADDSTRING = &H180
Public Const LB_INSERTSTRING = &H181
Public Const LB_DELETESTRING = &H182
Public Const LB_SELITEMRANGEEX = &H183
Public Const LB_RESETCONTENT = &H184
Public Const LB_SETSEL = &H185
Public Const LB_SETCURSEL = &H186
Public Const LB_GETSEL = &H187
Public Const LB_GETCURSEL = &H188
Public Const LB_GETTEXT = &H189
Public Const LB_GETTEXTLEN = &H18A
Public Const LB_GETCOUNT = &H18B
Public Const LB_SELECTSTRING = &H18C
Public Const LB_DIR = &H18D
Public Const LB_GETTOPINDEX = &H18E
Public Const LB_FINDSTRING = &H18F
Public Const LB_GETSELCOUNT = &H190
Public Const LB_GETSELITEMS = &H191
Public Const LB_SETTABSTOPS = &H192
Public Const LB_GETHORIZONTALEXTENT = &H193
Public Const LB_SETHORIZONTALEXTENT = &H194
Public Const LB_SETCOLUMNWIDTH = &H195
Public Const LB_ADDFILE = &H196
Public Const LB_SETTOPINDEX = &H197
Public Const LB_GETITEMRECT = &H198
Public Const LB_GETITEMDATA = &H199
Public Const LB_SETITEMDATA = &H19A
Public Const LB_SELITEMRANGE = &H19B
Public Const LB_SETANCHORINDEX = &H19C
Public Const LB_GETANCHORINDEX = &H19D
Public Const LB_SETCARETINDEX = &H19E
Public Const LB_GETCARETINDEX = &H19F
Public Const LB_SETITEMHEIGHT = &H1A0
Public Const LB_GETITEMHEIGHT = &H1A1
Public Const LB_FINDSTRINGEXACT = &H1A2
Public Const LB_SETLOCALE = &H1A5
Public Const LB_GETLOCALE = &H1A6
Public Const LB_SETCOUNT = &H1A7
Public Const LB_MSGMAX = &H1A8

' Listbox Styles
Public Const LBS_NOTIFY = &H1&
Public Const LBS_SORT = &H2&
Public Const LBS_NOREDRAW = &H4&
Public Const LBS_MULTIPLESEL = &H8&
Public Const LBS_OWNERDRAWFIXED = &H10&
Public Const LBS_OWNERDRAWVARIABLE = &H20&
Public Const LBS_HASSTRINGS = &H40&
Public Const LBS_USETABSTOPS = &H80&
Public Const LBS_NOINTEGRALHEIGHT = &H100&
Public Const LBS_MULTICOLUMN = &H200&
Public Const LBS_WANTKEYBOARDINPUT = &H400&
Public Const LBS_EXTENDEDSEL = &H800&
Public Const LBS_DISABLENOSCROLL = &H1000&
Public Const LBS_NODATA = &H2000&



Any idea what I'm doing wrong?
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Skywing

Maybe you're trying to insert items into the wrong listbox?  Starcraft uses several listboxes in the Battle.net chat UI, and just assuming the first one you get with FindWindow is the right one is probably a bad idea.

BTW, some of the Starcraft listboxs also have internal data structures associated with them and simply adding a string will be insufficient in some of these cases.

Don Cullen

Any suggestions as to how I can add text to that chat then without having it be broadcast to bnet?
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Skywing

Looking back on how I did it with SCE, there's a special window message you could send that would update all the internal state in addition to adding a listbox item so that the text would show up properly.

As I recall, it was something like so:



//
// Add a line to the chat output listbox.
//
// wParam is the default color for the line. [in] SC_COLOR wParam
// lParam is a pointer to the text (ANSI) to be added. [in] CONST CHAR* lParam
//
#define WM_STARCRAFT_ADD_LINE  (WM_USER+0x68)

enum SC_COLOR
{
  WHITE = 0x10,
  GRAY = 0x11,
  GREEN = 0x12,
  YELLOW = 0x13,
  BLUE = 0x14,
  RED = 0x19
};



I don't recall if this was sent to the parent SDlgDialog itself or the listbox; I found the window by watching for any window that Starcraft sent that window message to and caching the HWND for later use.

Remember that you will need to do custom marshalling for your text string (i.e. VirtualAllocEx a buffer in Starcraft address space, WriteProcessMemory the contents of the buffer, pass the Starcraft-space-relative pointer to SendMessage as the lParam, and call VirtualFreeEx to release the buffer after SendMessage returns).  If you pass a buffer pointer relative to your address space, Starcraft will either crash or write garbage to the screen.

There is a bug in Battle.snp's UI handling that will cause garbage data to be written to the screen if you write a line that is exactly the length for a line wrap, but not enough to write an additional character on the wrapped line.

Don Cullen

How would this be done in VB? Also, what is custom marshalling? Thanks for the help thus far, by the way!
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Don Cullen

Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

l2k-Shadow

Quote from: replaced on November 04, 2006, 11:54 AM
I dunno wat it means, someone tell me whats ix86 and pmac?
Can someone send me a working bot source (with bnls support) to my email?  Then help me copy and paste it to my bot? ;D
Já jsem byl určenej abych tady žil,
Dával si ovar, křen a k tomu pivo pil.
Tam by ses povídaj jak prase v žitě měl,
Já nechci před nikym sednout si na prdel.

Já nejsem z USA, já nejsem z USA, já vážně nejsem z USA... a snad se proto na mě nezloběj.

Don Cullen

Quote from: Skywing on February 14, 2006, 03:27 PM
Looking back on how I did it with SCE, there's a special window message you could send that would update all the internal state in addition to adding a listbox item so that the text would show up properly.

I don't recall if this was sent to the parent SDlgDialog itself or the listbox; I found the window by watching for any window that Starcraft sent that window message to and caching the HWND for later use.

How was that done, finding the window? What program did you use?

And |2-Shadow- thanks for help!
Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Grok

Spy++ can watch for specific messages, specific window traffic, and more.  You can find Spy++ in your tools directory of the Visual Studio install.

Don Cullen

Regards,
Don
-------

Don't wonder why people suddenly are hostile when you treat them the way they shouldn't be- it's called 'Mutual Respect'.

Skywing

Quote from: Kyro on February 15, 2006, 12:02 PM
How was that done, finding the window? What program did you use?

And |2-Shadow- thanks for help!

SCE itself hooked SendMessage to do this dynamically at runtime.  I'm sure you could find a different way to find the window without injecting a DLL with a bit of research.