This needs completely re-written to be more "frequently" asked questions; some of these are no longer relevant or correct. Use at your peril.
You will want to look at the ANS documentation for details on vocabularies. Look under the help menu on the Forth console. There is an entry that will open the ANS document for your perusal.
No special tools, I used Windows Paint, and edited them up. I would recommend that you copy the file WINDEMO.BMP to another name, then edit the icons in it with Paint, and then include that new file in your application for its toolbar.
That is correct, using the letters 'd' and 'e' alone, or in combination with legal numbers, does not produce an error. These are floating point numbers, per the IEEE floating point number format. If you use the floating point stack display word "F.S", then you will see that a number has been put on the floating point stack.
There is an empty colon definition called BREAKER that is defined as follows;
: BREAKER NOOP ;
If you use it like this;
:M WM_TIMER ( --- ) BREAKER ....the definition of WM_TIMER.... ;M
Then say this at the Forth command line before running your program;
DEBUG BREAKER
Then the Forth debugger will be invoked when the break point is encountered in BREAKER. Then use the 'U' command to debug UP to the definition of WM_TIMER. Not elegant perhaps, but functional.
Instance variables created with "int" are, or were private until I added the dot notation syntax to allow access to them. So I guess there really are no privates now. They are local however, since you can define a variable with the same name in multiple classes and objects.
This is an understandable confusion point. Andrew's example (HELLO.F) was implemented without using classes, so it had to do everything brute force.
WINHELLO.F on the other hand was implemented using the WINDOW class, which will automatically scan the HelloWindow class and object looking for windows messages as identified by the WM_ prefix and their existence in the WINCON vocabulary. These constants are then treated as window messages and when a window message of that type is received, it is passed to the appropriate WM_ method. Methods not defined are handled by a default windows message handler.
Here is an extract from WINDOW.F. (WndProc) is the window callback procedure that is called whenever windows wants to send a message to a Win32Forth window. The first part of this definition just deals with a special case having to do with window creation. I don't fully understand the details, so I won't explain it to you.
: (WndProc) ( hwnd msg wparam lparam -- res ) [ also classes ] GWL_USERDATA 4 pick Call GetWindowLong ( object address ) ?dup 0= if 2 pick WM_CREATE <> if DefaultWindowProc exit then dup abs>rel @ \ window object pointer from \ first cell of CREATEPARMS 4 pick ( obj hwnd ) 2dup GWL_USERDATA swap Call SetWindowLong drop \ save pointer over ! \ set hWnd parameter of window struc then
Here we look for window messages that we have defined. If it isn't, defined then we pass control off the "DefWindowProc: [[ ]]" which allows the user to redefine for each window a new default window procedure if needed. If the WM_ message is defined, then it is executed by the "catch" and if no error occurs, then the callback just returns to window.
3 pick ( msg ) over >class MFA ((findm)) if sp0 @ >r sp@ 4 cells+ sp0 ! dup>r catch ?dup if r@ WndProcError then r>drop r> sp0 ! else \ -- a1 \ the object address DefWindowProc: [[ ( a1 -- ) ]] \ gets used here then [ previous ] ; ' (wndproc) WndProc TheWndProc
DefWindowProc: is defined here, to allow any window to recognize a WM_WIN32FORTH message if one is defined. Otherwise control is passed to "DefaultWindowProc"
:M DefWindowProc: ( h m w l -- res ) 2 pick WM_WIN32FORTH = if Win32Forth: [[ self ]] 0 else DefaultWindowProc then ;M
If you don't understand all this, don't feel bad. There is much that I don't understand either. Andrew did all the really hard work, in figuring out how to get it to work the first time. The primary thing you need to know, is that if you define a window message (one starting with WM_) in a window, then your method will get called if windows sends your window that message. The details are messy, but the way it works in Win32Forth, covers much of those details.
Win32Forth is case insensitive, except when using the CALL word to call a Windows procedure. The procedure names "as you enter" them in the source, are used to access the names right out of the DLL, and as such are case sensitive.
If you are running Win32Forth 3.0 or higher and the DLL you are trying to access is a 32bit DLL, then you should be able to simply add a WinLibrary statement like this to your application:
WinLibrary MYDLL.DLL
Then you just call the dll functions within your application with something like;
CALL MyDllFunction
Be sure to put all its arguments on the stack in reverse order, that is the argument nearest the word CALL is the argument that appears first in the C call description.
NOTE: Win32Forth searches all the DLL's for a particular function name, and compiles a reference to which ever library it first finds the function in. So if you have conflicting function names, you will have a problem.
Starting with Win32Forth verson 3.2, each window can have its own menubar. Look at the example program WINMULTI.F for an illustration of how to create a multiple window application.
Begin by looking at here. You'll find a brief description and a couple of examples of how to use Object Oriented Programming in Win32Forth.
In addition, since Andrew McKewan ported the NEON (yerks/MOPS) model of object oriented programming to Win32Forth, the MOPS manual is very similar in usage and concept to the OOP model used in Win32Forth.
Versions 3.0 and later include some reworked Controls code that makes it at least possible to create dialogs (really modal windows) without having a dialog editor. Look at the example WINDILOG.F for an example of how to do this.
Versions 6.08 and later include a GUI Form Designer, ForthForm the manual for which is here
If you're using Win9x then Michael Hilleström's DiaEdit ( available here ) can be used to create dialog resource ( .RES ) files and source code files ( for DialogRC.f )
Dialog resource ( .RES ) files can also be created with the dialog editor which is included with the Free LCC compiler available here
:M On_Init: ( -- ) ;M :M WM_CREATE ( h m w l -- res ) On_Init: [[ self ]] 0 ;M
In the above example, "On_Init:" is a method that does nothing special, in fact it does nothing at all, except become a place holder for the use of "On_Init:" in the following method WM_CREATE. All of the WM_ methods n Win32Forth are called during a callback from Windows, when it wants to send, in this case, a window create message (WM_CREATE). When this happens, then the WM_CREATE method will call the On_Init: method. The double brackets "[[ self ]]" signify a runtime specified reference to On_Init:, so if you have redefined On_Init:, then your definition of On_Init: will get called instead of the default no operation shown above. is sort of an automatic re-definition linkage for methods defined with [[ self ]].
Your second question relates to the fact that the stack seems to be left in a odd state. Well, you are right, it isn't cleaned up before returning from the WM_CREATE method, but it doesn't need to be. You see the WM methods are called only from a windows callback, which means that windows calls Forth, and during that process, stacks are created for the method to use during execution, and they are destroyed when the method returns to window, so it doesn't make any difference that things are left on the stack. Each WM_ method should return a zero if message processing was completed without errors. In fact, it is better to leave extra things on the stack, than to have a stack underflow.
Well, excluding user interface, Forth is pretty much Forth, though Win32Forth is a linear addressed 32bit Forth versus F-PC's 16bit, which leads to the normal 2+ versus 4+ (or CELL + for ANSI) problems. The biggest problem you will have in using Win32Forth, is it is ANSI compatible, not F-PC compatible, so the file words are different. Win32Forth also adds full object oriented support (ala NEON or MOPS) which is a whole new way of thinking about programming.
I must warn you that excluding the user interface in Windows, or even F-PC, is to discard a large part of the application.
The other problem you will run into, is that Win32Forth only has access to hardware as it is made available through the Windows operating system, so access to hardware is extreamly restricted. Primarily you can access serial ports and the printer port.
Win32Forth includes several demonstration programs, these are the only examples available. Note that WINEDIT does popup a generic edit box that is built into Win32Forth to accept input from the user for the simpleest form of text search while in browse mode. You could copy that method and avoid creating your own windows. if you want to get simple single parameter input.
That's not possible. You can only set the foreground and/or background color for the complete console with FGBG!.
Ok, you can alway's use some windows API functions to set the console font and type some text like this:
Font vFont WinDC CurrentDC : texttest cls GETCOLROW gotoxy cr CONDC PutHandle: currentDC \ initialize DC to the console ltred SetTextColor: currentDC 10 Width: vFont 18 Height: vFont 0 Escapement: vFont Create: vFont s" Arial Black" SetFaceName: vFont \ default to Courier Handle: vFont SetFont: currentDC 120 160 ( x y ) s" Win32Forth " textout: currentDC 0 35 gotoxy ; texttest
But every time the console window receives a WM_PAINT message (e.g. if you resize the window) your output in the console window will be lost because the WM_PAINT handler of the console window (in TERM.CPP) repaint's the complete client area of the window with it's own data.
FOREGROUND and BACKGROUND doesn't work for the console window. The only way to set the foreground and/or background color for the console window is using the word FGBG! like this:
Color: red BG@ FGBG! \ set red foreground color FG@ Color: blue FGBG! \ set blue background color
To work with the console window FOREGROUND and BACKGROUND should be replaced with:
: FG! { color_object -- } color_object ?ColorCheck drop Color: color_object BG@ FGBG! ; : BG! { color_object -- } color_object ?ColorCheck drop FG@ Color: color_object FGBG! ;
Example If you VIEW FLOAD it takes you to line 59 of PRIMUTIL.F where the
synonym INCLUDE is declared to be a synonym of fload.
It should take you to the source for fload which is actually on line 4,811
of KERNEL.F
Some times this is not so big a problem when the synonym is declared with in
a few lines of the original work. But it is a bug.
Well, it's a problem, admittedly, but its not a bug; just the way SYSNONYMs and ALIASes work. They're identical to the words they shadow, and the vocabulary can't tell the difference.
.. c" FLOAD" find .s [2] 5285076 -1 ok.. .. c" INCLUDE" find .s [2] 5285076 -1 ok..
As you can see, the same entry is returned for both. VIEW INCLUDE takes you to
the same place but in this case it is good.
Some times this is not so big a problem when the synonym is declared with in
a few lines of the original work. But it is a bug.
in some classes I have see something like:
:M Foo: ;M :M Foo1: Foo: [ self ] ;M
can someone tell my what's the differece beetween this and:
:M Foo: ;M :M Foo2: Foo: self ;M
is?
[ SELF ] is a late bound call to SELF whereas SELF is early bound so
:CLASS myclass <SUPER OBJECT :M Foo: ." Foo: from myclass" ;M :M Foo1: Foo: SELF ;M :M Foo2: Foo: [ SELF ] ;M ;CLASS :CLASS myclass2 <SUPER MYCLASS :M Foo: ." Foo: from myclass2" ;M ;CLASS myclass myobj1 myclass2 myobj2
would produce the same message for both objects for Foo1: but different ones for Foo2: since Foo2: myobj2 would find the second Foo: in myclass2 whereas Foo1: was bound to the original Foo: when it was compiled.
The Foo: [ self ] notation is used to enforce late binding, so for
example, if you redefine a new method Foo:, in a subclass, then it will
get used instead of the original Foo:, but only if you late bind (runtime
bind).
Essentially it allows forward references, or redefinitions, and is
often used in the way you describe, with self, so a particular method
doesn't have to be fully functional at the time the class is created.
You can use FCALL to call a Forth word within assembler code.
code x fcall DUP push ebx mov ebx, # 10 fcall DUP next c; is the equiavlent of : X DUP 10 DUP ;
You can use FCALL to call a Win32 API function within assembler code.
code x fcall AllocConsole next c; is the equiavlent of : X call AllocConsole ;
Document $Id: p-faq.htm,v 1.1 2004/12/21 00:18:56 alex_mcdonald Exp $