You guys got me feeling all bad that i have to bail for a few days after I rally'd people's interest.. so im posting OBJECTS.INC here with an example program.

There is two classes.. NO inheritance. (keeping it simple)

I wrote a DC class to handle the creation of DC's etc for drawing graphics. Its (CHDC - Class HDC ).

I wrote a CBButton class (Class Bitmapped Button) to create Owner drawn buttons (by the class).

The rest is a basic message loop frame, to make a WinAmp type custom window (the way it roles up in minimized mode).

I havent documented it all to much tho. But OBJECTS.INC is very well documented!!! I suggest you read it over as you study the code. I put hours into documenting each macro, crossing my 'i' and dotting my 't's.. heheh :)

I hope it will help you see how the moster works.

Enjoy! Post messages, i *will* eventually get back to them. Or perhaps Thomas will beat me to the punch...


The file is 100K of graphics and 8K code. Get it off my web site, as i cant upload over 30K here --> First Item On the Page - "RockStar"

:alright:
NaN
Posted on 2001-09-20 01:13:47 by NaN
hehe... That's a pretty spiffy program... To bad I don't understand it yet :alright:
Posted on 2001-09-20 13:17:12 by Kenny
Yea me neither.. but I really want to learn it! any chance for a nice n easy tutorial sometime??
Posted on 2001-09-21 16:10:06 by closed_casket
Thomas posted a good tutorial in one of the other topics. Seems as if everything is the same as writing a single GDI program, but the difference is where he makes stuff an object that can do many things. (Kind of taking the specialization of ASM away in a good way.)

I suppose writing something using these classes would be pretty easy. Take the windows proc of the GDI examples and just build on those. I think the fastest way to learn would be to make an object that displays a message box. "Hello world" is always the easiest :)
Posted on 2001-09-21 16:29:30 by Kenny
I posted a more simple example in this thread: . It doesn't show all things that can be done with objects.inc, only the basic things, inheritance & superclassing..
No comments or tutor either.. sorry for that, it's the usual problem: lack of time.. I'll try to write some tutor tomorrow.

Thomas
Posted on 2001-09-21 16:33:18 by Thomas
Kenny: you beat me with your post :)
It is a simple GDI program just because that's the first thing I could think of to demonstrate the objects in a good way.. The important part here is that you can see that each object has it's own properties, and although one method (move) is called the same way for each object in the array, all objects draw their sprites according to their own properties.
This is the most important thing about classes.
btw the example wastes a lot of resources as it loads the bitmaps again and again for each object, this could be optimized but to keep it simple I didn't.

Thomas

(p.s. the program is much more fun when you set the MAX_SMILIES value to 1000 :grin: )
Posted on 2001-09-21 16:38:38 by Thomas
Give me an idea of what kinda tut you want...

Heres a start tho:

    [*]Objects must be instanciated, this is actually creating a new Object from the Class template. You use the NEWOBJECT() or $NEW() macro's to do this.

    [*]Objects, are created on the HEAP. So you should destroy them when your finished. (Test show that windows does for this if you dont, but its not recomended ~ cant promise you wont get memory leaks. You do this by using the DESTROY() macro.

    [*]Anything with a '$' before it is an accelerator macro. They are to make code more readable (like a HLL line of code). If they are a label name ($NEW) then it always replaces itself with the 'eax' register when the macro is resolved by the compiler. $EAX(), $EBX(), $ESI(), and $EDI() are all METHOD() accelerators. They act the same as METHOD(), except when resolved by the compiler, they are replaced by either eax, ebx, esi, or edi respectively. I chose these as they are the least likely registers to be altered by any method code etc. Long story short, they can make 2 lines of code into : mov hNewObject, $NEW( MyClass )
    would be the same as: NEWOBJECT( MyClass ), mov hNewObject, eax.
    [*]METHOD() is like invoke. Except you have to give the Object you with use with the method fucntion you want to call, as well as give the class type the method is found in. The rest is exactly like invoke, methodname, and optional parameters.

    [*]CLASS() macro is a MUST. It tells the other macro (used later in the class file) the name of your class.
    [*]CMETHOD() macro "Class Method", builds the needed MASM32 layout for function pointing in the Class structure. Is is only used here. It also helps you visually distinguish the methods from the variables in the structure.

    [*]BEGIN_INIT and END_INIT are a must. They set up pointers for the compiler as to where all the method offsets and initial values can be found for your class. The method offsets MUST be in the same order as the CLASS structure.

    [*]SET_CLASS .... INHERITS .... This is ONLY in the constructor of your class definition. It will place needed code to intialize an instance of your class, settin all its method pointers and inital values. As well, if the INHERITS SomeOtherClass is present, it will call the constructor of the of the class it inherits (were its only SET_CLASS code will act further. Long stoy short, it will recurse every level of inheritance back to the base class, and perform their constructors at each level.

    [*]SetObject() and ReleaseObject(). These are simple macros used to make your method coding easy, when refering to the classes own data members (variables etc). In practice we have adopted the use of "edi" for this purpose, such that EDI can be assumed as the pointer to the intance's object. (edi == lpTHIS). You must tell it what type of class it is to be assumed as. And MUST release it when finished (or wierd bugs could creep up). These allow users to do this: mov eax, .FileSizeVariable. Where as with out this you would have to do: mov eax, (ClassType PTR ).FileSizeVariable.

    [*]OVERRIDE() can be used anywher, but SHOULD be used ONLY in the constructor. It works with classes that inherit. It adjusts an instances method pointer (Set by SET_CLASS), to point to a new method proc. This produces POLYMORPHISM, as the method PROTO remains the same (and thus the new proc should have the same # of parameters).

    [*]SUPER() Is used for Polymorphic method procs. If you decide you want to OVERRIDE a method inherited, and do the same thing plus a bit more as well, you can REUSE the old code with the SUPER() macro. Calling SUPER( methodname ) will run the inherited proc, and return back into the proc it was called from. From there you simply add the extra code to make the two Polymorphically different

    Knowing all this.. i can made a Class template now by hand quite simply:
    
    
    ; Class name: Sample

    ; NOTE: constuctor and method proc's MUST have at least
    ; one DWORD param. This is because METHOD will
    ; always pass the object instance's address in the
    ; first param (lpTHIS).

    ; Constructor proc, not included in class structure.
    ; Must be: ClassName + _Init

    Sample_Init PROTO :DWORD

    ; Method Proto's : MUST be named in the followin format
    ; Abreviated Name as specified by the CLASS macro with a "_"
    ; MethodName
    ; Followed by "Pto"
    ; >> Abv_MethodNamePto

    Sample_Method1Pto TYPEDEF PROTO :DWORD, :DWORD

    CLASS Sample ; no second argument means Abv = "Sample"
    CMETHOD destructor ; MUST BE FIRST IN ALL CLASSES!
    CMETHOD MethodName
    myData dd ?
    Sample ENDS

    .data

    BEGIN_INIT
    dd offset DestructorProc
    dd offset MethodProc
    dd NULL ; << myData initial value when instance is created
    END_INIT

    .code
    ; Now just code your method functions.
    ; You must have the Class_Init constructor function,
    ; and a "destructor" Proc in every class.
    ;
    ; NOTE: the first param MUST be defined as "lpTHIS" to work

    DestructorProc PROC uses edi lpTHIS:DWORD
    SetObject edi, Sample

    ; return the myData when an instance is destroyed...
    mov eax, [edi].myData ; [edi] because of SetObject

    ReleaseObject edi
    ret
    DestructorProc ENDP

    Sample_Init PROC uses edi esi lpTHIS:DWORD

    SET_CLASS Sample ; fill instances with class method ptr's

    ; Any other inits you need to do..
    ret
    Sample_Init ENDP

    MethodProc PROC uses edi lpTHIS:DWORD
    SetObject edi, Sample

    ; you method function...

    ReleaseObject edi
    ret
    MethodProc ENDP


    Thats it.. This is how a class template is defined.. Now to do all this manualy can be a bit, so I created the Creator Tool to do just this stuff for you. But you should understand this, if you want to add more methods (ie. Add a "TYPDEF PROTO", Add a new CMETHOD entry, add a offset to the BEGIN_INIT/END_INIT area, build a method proc like the ones above. ). Adding a variable only requires the Class and INIT entry's.

    Hope this is a helps...
    NaN
Posted on 2001-09-21 17:24:39 by NaN
Thats it..


Seems like an aweful lot to do pretty much nothing :grin: (You know I'm just messing with ya right?)
Posted on 2001-09-21 21:49:52 by Kenny
NAN
i just copied and pasted your last post in this thread

Why

Because i have go so much help from you its gotta mean something


an ounce of prevention is worth a pound of cure
:alright:
Posted on 2001-09-21 22:30:17 by titan
I know your joking, and i do realize if you've never programmed objects the lingo can be a bit much. All i can say is practice a bit, and ask questions.

But it really isn't all too much to do the above nothing, when you chop out the comments its not that big (trust me, these macros make the needed suport code ALOT less (especially SET_CLASS and CMETHOD):


Sample_Init PROTO :DWORD
Sample_Method1Pto TYPEDEF PROTO :DWORD, :DWORD

CLASS Sample
CMETHOD destructor
CMETHOD MethodName
myData dd ?
Sample ENDS

.data

BEGIN_INIT
dd offset DestructorProc
dd offset MethodProc
dd NULL
END_INIT

.code

DestructorProc PROC uses edi lpTHIS:DWORD
SetObject edi, Sample

mov eax, [edi].myData ; [edi] because of SetObject

ReleaseObject edi
ret
DestructorProc ENDP

Sample_Init PROC uses edi esi lpTHIS:DWORD
SET_CLASS Sample

ret
Sample_Init ENDP

MethodProc PROC uses edi lpTHIS:DWORD
SetObject edi, Sample

ReleaseObject edi
ret
MethodProc ENDP
Posted on 2001-09-21 22:53:37 by NaN