Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ VBscript ➜ Adding window with info about character

Adding window with info about character

It is now over 60 days since the last post. This thread is closed.     Refresh page


Pages: 1 2  

Posted by Zuurstof   (13 posts)  Bio
Date Fri 20 Feb 2004 12:30 PM (UTC)
Message
Hello

I would like to try and create the following, I have no idea if it's possible though. But at my mud all the info about your character is in different commands.
vb:

score:
Draven of Cuiviénen the silvan Highlord (Bane of Angband)
HP: 230/230 END: 221/230 Exp: 2100188 Avg. Stats: 100
Strength: 100 Agility: 100 Charisma: 100
Constitution: 100 Coordination: 100 Intelligence: 100
Level 20 warrior, 24d 6h 57m 36s old.

skills:
Common Skills:
Aim : 100 Attack : 100 Awareness : 100
Defense : 100 Dodge : 100
Fire building : 100
Riding : 100

Professional Skills: Other Skills:
Blind fighting : 100 Deception : 60
Blocking : 100 Disguise : 2
Combat arms : 100 Wilderness : 60
Tactics : 100

Languages:
You are 100% fluent in variag.
You are 100% fluent in adunaic.
You speak khuzdul very well.
You are 100% fluent in sindarin.
You can speak easterling a little bit.
You speak black passably.
You are 100% fluent in westron.
You are 100% fluent in rohirric.
You are 100% fluent in orcish.
You are 100% fluent in silvan.


Now it would be nice to create an extra little window inside mushclient that constantly shows and updates this data.

I was thinking about writing a dll and calling it from mushclient. filling the new window with the data send by mushclient somehow. I have no real idea how to do this though, and if it's even possible. The same idea goes when trying to create an extra window to show your equipment.
With extra window I mean a window created in vb or something that I call from mushclient. So the new window will be only visible when mushclient is not minimised.

I'm not sure if anybody understand what I mean, but I hope so. Let me know if you think you know how to do this.

Greetings Zuurstof

Top

Posted by Zuurstof   (13 posts)  Bio
Date Reply #1 on Fri 20 Feb 2004 07:48 PM (UTC)
Message
Hmm, well I discovered how to call a dll, give a msgbox and show a form, the only problem with that is that the form has to be modal, which would make me unable to type anything while the form from my dll is open. Can't I make it a mdi-child form of the application somehow. I guessing no, but maybe somebody out there knows a solution.
Top

Posted by Shadowfyr   USA  (1,791 posts)  Bio
Date Reply #2 on Fri 20 Feb 2004 08:19 PM (UTC)

Amended on Fri 20 Feb 2004 08:25 PM (UTC) by Shadowfyr

Message
Yeah. I know exactly what you mean. Basically, the best bet is a plugin that calls the dll. You would do something like this:

1. Make new AvtiveX Exe or Dll project - MyWindow
2. Add a Richtext control to the main form.
3. Add a class module NewWindow, this will be what you 'create' with createobject("MyWindow.NewWindow").
4. Add a .BAS file (Module), add the API call code for retrieving the window size and some other stuff from a handle to this module. It must be in a regular module to work:

Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hwndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wflags As Long) As Long

Public Const HWND_TOPMOST = -1
Public Const HWND_NOTTOPMOST = -2
Public Const SWP_NOACTIVATE = &H10
Public Const SWP_NOSIZE = &H1
Public Const SWP_NOMOVE = &H2

Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

GetWindowRect is used to get the current size of the Mushclient window. As of 3.43 and 3.44 you can now request a handle for Mushclient's main window. There are also callbacks from plugins that identify when the world has gained or lost focus. To detect if Mushclient has minimized all you do is check the size of the main Mushclient window, since it should then be something like 0,0,0,0. So basically your plugin would do:


set Mywindow = createobject("MyWindow.NewWindow")

sub OnPluginLoseFocus
  Mywindow.CheckSize(GetFrame)
end sub

sub OnPluginGetFocus
  Mywindow.CheckSize(GetFrame)
end sub

Then in your VB program you would do (in the class module):

sub CheckSize (hwnd AS long)
  dim TRect as RECT
  GetWindowRect hwnd, TRect
  if TRect.Left = 0 and TRect.Right = 0 then
    MyWindowFrm.windowstate = 1
  else
    MyWindowFrm.windowstate = 0
    SetForegroundWindow hwnd 'Return control to Mushclient.
  end if
end sub


Note: I may have the window state backwards there..

SetWindowPos is used to make it always-on-top, you would use: HWND_TOPMOST along with 'SWP_NOACTIVATE OR SWP_NOSIZE OR SWP_NOMOVE' to make it on top, but not change any other settings. This means that if minimized it will remain so and you can use 0,0,0,0 for the X,Y,Cx,Cy values. If you left off the flags, it would resize the window to those values and give it focus.

You can also use the command (note I added it above too):

SetForegroundWindow hwnd

to return the focus to Mushclient (in the class module):

sub Return_Focus (hwnd AS LONG)
  SetForegroundWindow hwnd
end sub


There is unfortunately no way to do this when the class is initialized, since even if you linked the mushclient.tbl file into the project, it has no connection to the world file until *after* the object already exists. Unless you want to send stuff to the mud from the project, it is just as easy to pass the window handle from the plugin each time, instead of using the linked .tbl file to ask for it internally to your project. In theory you could, once you have the handle the first time, save it in a global variable and reuse it (placed in the same .BAS module as the API declarations). This may or may not fail in some cases, so it is safer to make sure you have the right handle each time you need it.

However, other values you may need global are best placed in that same .BAS module, since that way 'all' parts of the program can use them. ;)

4. Finally, add in some code to display your text. Since you used a RichText control, you could in theory take appart the entire captured line and rebuild it in the output. Or you can do it the easy way and just paste more text into the window.

It may also be a good idea to add code to check if you intentionally minimized the window and leave it that way, since any time you leave the Mushclient window for 'any' reason it will cause a LoseFocus event and then a GetFocus when returning. If you intentionally minimized the window, then it will immediately pop back up as soon as this happens using the simple code above.

Anyway.. This is the basics. Anything accessible to the plugin needs to be part of the class module. Attributes (things you set or retrieve with Mywindow.value = 0 and the like) use Property Let and Property Get to make them accessable. This should hopefully give you a good start.

---
Heh Nick.

My only real complaint now is that dragging the Mushclient window smaller or larger still doesn't create an event that can be trapped, so if you want a window that resizes with Mushclient, you still have to periodically get the window rectangle and check to see if it changed from the prior time you checked. Something like an OnPluginFrameResize event (and the same main world event) would be quite a bit nicer. The only alternative is a nasty trick for trapping window events (by inserting a filter into the OS) and if you screw that up in any way it will freeze the computer. :(

It may be useful to have WorldResize events too, since you way change the number of available columns that a script can use for output and their is no existing way for the script to know this. You need both events though, since the Frame could change without effecting the size of the world and the other way round.
Top

Posted by Shadowfyr   USA  (1,791 posts)  Bio
Date Reply #3 on Fri 20 Feb 2004 08:44 PM (UTC)
Message
Oh.. BTW. Three things to remember.

1. Make sure that the class is set to allow multi-use.

2. Always use the File menus option to create the complete DLL or EXE and use Mushclient itself to test the result. Using Run means it will not create either a permanent file or a permanent Registry entry, so you can't use it 'except' in the VB editor.

3. Exe is generally better, since one feature of VB ActiveX Exe files is that you can usually run them like a normal program the first time in order to make them available to the user.

This means that you can send someone a copy of the file, without an installer and they can just double-click the program, then immediately start using it. In theory you could even make you script do:

on error resume
set a = createobject("MyWindow.NewWindow")
on error goto 0
if typename(a) <> "MyWindow" then
... 'Add code to run the Exe or here.
end if

I am not sure about the 'type' returned. I believe it will be the name of your object. For instance the Winamp COM control gadget shows: IApplication when typename is used.

You may be able to use Rundll32.exe this way as well to register a DLL file. I haven't actually tried this, but it *should* work in theory and doesn't require the guy installing the plugin to do anything with the EXE or DLL except unzip the files into the plugins directory set their world to load the plugin.
Top

Posted by Nick Gammon   Australia  (23,165 posts)  Bio   Forum Administrator
Date Reply #4 on Fri 20 Feb 2004 09:36 PM (UTC)
Message
I was going to suggest capturing the output and sending to a notepad window, but a separate program would probably be neater, if a lot more work. :)

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Zuurstof   (13 posts)  Bio
Date Reply #5 on Sat 21 Feb 2004 01:18 PM (UTC)
Message
Thanks for the quick reply, I've understand most of your messages. It's still a bit fuzzy but i'll probably get it when i'm programming it. Anyways I still have a couple of questions though.

1:
You say: As of 3.43 and 3.44 you can now request a handle for Mushclient's main window.

I only have version 3.42, and I can't find the versions you are talking about on the website. Is the explanation you give based on these newers version??


2:
1. Make sure that the class is set to allow multi-use.
What you mean with this?:)

3:
I still haven't really heared how I would show the form.
Cuz now I have the following code:

Project name: Arda
Class name: cMain

class code:
Public Sub setParameters()

MsgBox "test"
frm.Show vbModal
End Sub

in script:
Sub start(thename, theoutput, thewildcards)
set obj = createobject("Arda.cMain")
obj.setParameters
End Sub


Now this creates the object, and shows the messagebox alright. Then it shows the form, but it's modal. So I can't type anywhere. If you know another way of calling the form without it being modal and it will work in mushclient, that would solve a lot of my problems. Mushclient should be the parent of an mdi-child I show. Well that's the same principle at least..

Greetings
Zuurstof



Top

Posted by Flannel   USA  (1,230 posts)  Bio
Date Reply #6 on Sat 21 Feb 2004 07:26 PM (UTC)
Message
3.44 Can be found here...

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=3772&page=1

Nick tends to release new versions, and then only once stable, etc post it on the main site.

~Flannel

Messiah of Rose
Eternity's Trials.

Clones are people two.
Top

Posted by Shadowfyr   USA  (1,791 posts)  Bio
Date Reply #7 on Sat 21 Feb 2004 07:40 PM (UTC)

Amended on Mon 23 Feb 2004 12:08 AM (UTC) by Nick Gammon

Message
1. These are new versions just released. Maybe the links are not updated yet. Check this thread:

http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=3772&page=999999

Included in 3.43 (which was buggy) was a new command 'world.GetFrame' that returns a handle to Mushclient's main frame. 3.44 also has it of course. The only other way to get the handle is to do:

In the .BAS module:

Declare Function EnumWindows Lib "user32" _
 (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean
Declare Function GetWindowText Lib "user32" _
 Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, _
 ByVal ccs As Long) As Long
Declare Function GetWindowTextLength Lib "user32" _
 Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long

dim DockWindow = "MUSHClient"

Public Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) _
  As Boolean
  Dim sSave As String, Ret As Long
  Ret = GetWindowTextLength(hwnd)
  sSave = Space(Ret)
  GetWindowText hwnd, sSave, Ret + 1
  If InStr(sSave, DockWindow) Then
    Winhndl = hwnd
    EnumWindowProc = False
  End If
  EnumWindowsProc = True
End Function

In your main code:
EnumWindows AddressOf EnumWindowsProc, ByVal 0&


This is what I used for a gadget that produces a firework display, in order to let me find the Mushclient window and resize the fireworks to fit snuggly next to it. Now if I where to recode the program, I would use the GetFrame technique instead, since it is a lot easier to have Mushclient tell me what the internal ID for its window is than to use all the above API junk to find it myself. Basically, the above code has to look through *every* window that has the system Desktop as a parent. That is all open programs, all system tasks, all tray icon based applications, etc., just to find the Mushclient window.

If you used it with a program whos title bar contained changing text or you could open multiple copies, forget even trying. Imagine for instance three copies of Notepad open. The above code only finds the 'first' one. You could maybe adjust it to find all of them, but then which one is the *right* one? I pestered Nick for a while about this before he caved and provided a better way. ;)

2. Actually I meant the project. There are several settings you can employ:

a. Multiple copies used by several different programs. This is the one you want. In think it is also the default.

b. A single copy of the object, but usable by more than one program. This is like most system services or databases, but is more complicated to manage, since you have to directly keep track of how many applications are connected, since the object cannot be destroyed until 'all' programs release it. If you do it like (a), then the first program to release a connection would destroy the object and every other program that thought it still existed would crash.

c. One instance, one use. I think... Only one program can use it at a time. This is probably for DLLs that are used by only your own programs. The expectation is that only one copy of your program will be running and that the DLL will not be used by anything except that program.

At least I think that is the options available. I am not 100% sure about (c) and there may be a fourth option as well.

3. Umm.. Why exactly are you using vbModal?? Just use 'frm.Show' without any other parameter. It defaults automatically to non-Modal. The only time 'anyone' uses the vbModal flag is in critical system applications that must 'lock' the machine until completed. It is bad practice to use it in your own programs, unless you absolutely need it. Even then, I think it is only Modal to the 'parent', though I am not positive. You may be able to make child windows Modal and not effect the OS, but in this case you are making the Top-Level window (the one whos only parent is the system Desktop) Modal and that locks all other programs, except the Taskmanager and 'maybe' system service applications. Best bet is just don't use vbModal. ;)

---

Oh, BTW. I just realized SetForegroundWindow is also an API call. You need to declare it in the .BAS module with the rest like:

Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long

Imho these things should all be built into VB, but like most MS products, they simplified the language to the point where even *basic* things you can do in pretty much any other language are unavailable to VB programmers. Bloody stupid.

The one that annoys me the most is that all controls (like buttons and stuff) have by default a 'design-time' mode. This is the same thing you see when building a form. The control lets you use the mouse to move them, resize them and you can change some settings like mutli-line in textboxes. If you code in C++ this mode is available to you in your own programs. In VB these functions are completely disabled at run-time, so you can't use/change them at all. But then who would want to design a VB application that let you design or change the layout of a form? **Me, you bloody idiots!!!!** lol
Top

Posted by Poromenos   Greece  (1,037 posts)  Bio
Date Reply #8 on Sun 22 Feb 2004 12:25 AM (UTC)
Message
You could use drag-and-drop to set the control position on the form...

Vidi, Vici, Veni.
http://porocrom.poromenos.org/ Read it!
Top

Posted by Shadowfyr   USA  (1,791 posts)  Bio
Date Reply #9 on Sun 22 Feb 2004 01:14 AM (UTC)
Message
Yes. You can 'fake' design time control, within limits. However, in the case of a textbox, you have to impliment both the multi-line and single-line version and then hide one and make the other visible to 'fake' it. Same with any other controls that have options that are only evailable in design time. Nothing like wasting memory on 20 object you are never going to use, just because you can't change one minor setting at runtime. With C++ you can simply switch the entire form into desing mode by changing the UserMode attribute and alter anything you want. If you want to be able to resize the control with the mouse, then you have to create fake drag box that fits over it, with control points and impliment a rediculous mess of code to resize the real control based on the fake drag box. This is imho rediculously complicated and stupidly redundant when all existing controls already impliment functions to do this already.

The form designer in VB and other programs don't impliment these things, they are *built-in* to the function of the controls themselves, so they know how to drag and drop, resize, etc. when in the correct user mode. A form designer is little more than a program that shows a form, provides a mess of options to add existing objects, links those things to the control array in the form you are using and lets you switch the whole thing in and out of design mode. If VB supported design mode at runtime, you could code an entire form designer in probably 100-200 lines of code. Instead they disable the ability to even use controls or forms in that mode and short of using 4-5 times as many lines of code in C++ to build a COM control that allows it, you have to spend 4-5 times as much code to fake 50% of the function that such a designer allows.

Its just another one of those 'features' of VB that make it inconvenient to design programs that actually work as well as something written in any other language.
Top

Posted by Poromenos   Greece  (1,037 posts)  Bio
Date Reply #10 on Sun 22 Feb 2004 03:11 PM (UTC)
Message
Isn't it possible to get the control to think it's in design mode? Maybe you couldn't change it back and forth though... Yeah, it's stupid if the controls already have the functionality :/

Vidi, Vici, Veni.
http://porocrom.poromenos.org/ Read it!
Top

Posted by Shadowfyr   USA  (1,791 posts)  Bio
Date Reply #11 on Sun 22 Feb 2004 07:37 PM (UTC)
Message
It is possible with a single line of code, *in C++*, but VB doesn't provide access to that function. It may be possible through an API call or some other indirect means, but I have lost track of the one example I saw that used it. Six hours of Googling yesterday failed to rediscover the article. :( I plan to keep looking though. It may be possible to impliment the option in a DLL written in C++ and use that class to manipulate the objects. However, at the moment it is only a working theory.

I am also trying to find out how IE impliments its feature for doing:

<OBJECT ID="Grid1" WIDTH=100 HEIGHT=51
 CLASSID="CLSID:A8C3B720-0B5A-101B-B22E-00AA0037B2FC">
    <PARAM NAME="_Version" VALUE="65536">
    <PARAM NAME="_ExtentX" VALUE="2646">
    <PARAM NAME="_ExtentY" VALUE="1323">
    <PARAM NAME="_StockProps" VALUE="77">
    <PARAM NAME="BackColor" VALUE="16777215">
</OBJECT>

I don't need the overhead of imbedded IE, which expects events from such controls to be handled by script anyway. I just need it, so I can add generic controls into a form within an XML definition file, so you can load a custom window with something like:

set a = createobject("MC_Companion.NewWindow")
a.loadform "forms\ObjectBrowser.xml"

of something of the sort.

There are roughly 232 such controls on my computer. Some of them are tied to other programs like 3D Canvas or RealPlayer, but even if you ignore all the ones that don't appear on everyone's machine, you still end up with at least 150 or more. It is real stupid to have to waste resources by pre-linking all these things into your program, just so they are available when you need them. Some people may also design their own controls to do some special thing and then what? They can't 'ever' use it in your program.

What I needed is a way to edit the layout in design time mode, then export the result to XML and reload it later. Finding an example of this that isn't precompiled and proprietary is proving very frustrating. :(
Top

Posted by Nick Gammon   Australia  (23,165 posts)  Bio   Forum Administrator
Date Reply #12 on Mon 23 Feb 2004 12:11 AM (UTC)
Message
Quote:

Nick tends to release new versions, and then only once stable, etc post it on the main site.


Does anyone who has been using version 3.44 had any problems with it, or can it become the official release?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Shadowfyr   USA  (1,791 posts)  Bio
Date Reply #13 on Mon 23 Feb 2004 01:13 AM (UTC)
Message
No problems I have found.
Top

Posted by Zuurstof   (13 posts)  Bio
Date Reply #14 on Mon 23 Feb 2004 09:11 AM (UTC)
Message
Well I still have the same problem. I'm not sure if anybody tried this or not but I try to open a form from my dll and it's non-modal then it just will crash.


error nr: -2146827882
error:
Non-modal forms cannot be displayed in this host application from an ActiveX DLL, ActiveX Control, or Property Page.


I can create a seperate program and send the data there I guess, but I want to screen to be inside mushclient. So that mushclient is a parent to my screen, if that is at all possible. If somebody could give a real simple example of how I can open a form(non-modal) from within a dll that is called from muchclient vbscript that would solve all my problems. I know how to ship data to it, I just can't open a form.


ps:

this code produced the error

project: Arda
class: cMain
Public Sub setParameters()
frm.Show
End Sub


vbscript in mushclient:
Sub start(thename, theoutput, thewildcards)
set obj = createobject("Arda.cMain")
obj.setParameters
End Sub


I have an alias that calls sub Start and that's it.
Let me know if you need any more information




Btw thanks for all the quick replies!

Greetings Zuurstof.
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


83,117 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.