IonicWind Software

Aurora Compiler => Tutorials and Documentation => Topic started by: kryton9 on June 09, 2006, 11:34:38 AM

Title: a request
Post by: kryton9 on June 09, 2006, 11:34:38 AM
I have a request for a tutorial. Can someone write a step by step on how to look up where to find an api function that one might need. How to decipher what is says on MSDN and turn it into something useable in Aurora. From what I can tell, all the api stuff is in a dll somewhere. How do you first of all know where to look? I do a search and MSDN brings up numerous functions that all seem the same to me.

So if you could find something that does the same thing... use an api function that might be in many dll's but in slight differences, and explain how you would go about knowing which to use and then how to use the information on MSDN for the selected function and understand what all their info says and then to convert that into Aurora variables and classes and methods. Thanks.

Assume that I know nothing. Which is pretty close. I know basic and derivatives, but not when it comes to external declares, classes, calling stuff from dll's and all that stuff. Windows variable naming and declaration is a mystery to me. I know they had a brilliant european set the standards and I am sure it means something and is probably brilliant, but to me it looks like giberish and mumbo jumbo :)ÂÃ,  It is like using the old hp calculators with the reverse entry compared to texas instrument's what I would call normal entry calculators. It might make alot of sense, but just seems really foreign and hard to sink my teeth into :)

Also anyone taking up this request please post that you are doing so before you are doing it, so that other's who might want to help also don't waste their time writing such a tutorial doing duplicate work. I know it will be a daunting request and time consuming, but I know something I really need to get me to another level of programming. And I am pretty sure would be very helpful to many programmers with my sort of background.
Title: Re: a request
Post by: Parker on June 09, 2006, 01:41:45 PM
1) Know what you want to find. If you don't know the function name, MSDN probably won't be able to find it.
2) Go to http://msdn.microsoft.com/ and type the name of the function in the search box.
3) Click on the entry that looks most like what you are looking for. Usually it says something like "Xxx Function" where Xxx is the name of what you are looking for. Note though, the ones that don't say "Function" after the name are usually for windows CE (handheld devices), so you probably shouldn't use those.
4) The parameters are specified usually in MS's typedefs used with C. You have to convert them to the equivalent Aurora intrinsic types.
5) If the function takes a string, and even if some that don't, it comes in two flavors: XxxA and XxxW. The "A" version is "ANSI" and the "W" version is "Unicode".

For an example, I'll walk you through converting CreateWindowEx.
1) We know exactly what we want to find: The function CreateWindowEx.
2) Go to MSDN and search for the function.
3) In this case (and most cases), the entry we were looking for was at the top. Click it, and you'll go to a new page.
4) I'll go over each parameter's type and the return type. We see under "Syntax" the line "HWND CreateWindowEx(", which means that it returns an HWND and is called CreateWindowEx. HWND is a handle type, and as with all handle types, can be implemented as an unsigned int. So for right now, we have the Aurora code
import unsigned int CreateWindowEx(
Now to convert all the parameters. First we see DWORD. This means a "double word", and if you're interested, it comes from the processor and assembly programming, where you deal with bytes, words, double words, and quadruple words. In Aurora, those types are equivalent to byte, word, int, and int64. Usually these types will be unsigned, as is the case with DWORD. So we have our first parameter:
unsigned int dwExStyle

Now on to the others. The next two are LPCTSTR, which means a pointer to a string, or in C a character array. You can represent it with either string or string*, they're identical in every way except string* lets you pass NULL, but since you can use "" anyway, I usually just use string.
string lpClassName,
string lpWindowName


The next parameter is a DWORD, like the first, so we can write
unsigned int dwStyle

The next four parameters are easy, because that's one of the rare cases where MS actually used an intrinsic type and not a typedef. Just keep them as is:
int x,
int y,
int nWidth,
int nHeight


Now we see one of those handle types I was mentioning above. There are many of them: HANDLE (generic handle), HWND (window handle), HBRUSH (brush handle), HDC (device context handle), HKEY (registry key handle), etc. Generally you can assume that when you see something with H at the beginning that isn't its own word itself, it is a handle. Those are converted as unsigned int. That being said, the next three parameters are unsigned int.
unsigned int hWndParent,
unsigned int hMenu,
unsigned int hInstance


The last parameter is an LPVOID. Whenever you see LP, and I didn't mention it above for LPCTSTR because that is an exception where you can use string, it is a pointer. Aurora isn't picky about types, so you can just use the pointer keyword there. However, I usually use void* because that is more consistant with other typed pointers, like unsigned int* (which does have at least one API typedef, LPDWORD). The last parameter is:
void *lpParam

Okay, so we've got all that converted, now let's put together a full declaration.
import unsigned int CreateWindowEx(
    unsigned int dwExStyle,
    string lpClassName,
    string lpWindowName,
    unsigned int dwStyle,
    int x,
    int y,
    int nWidth,
    int nHeight,
    unsigned int hWndParent,
    unsigned int hMenu,
    unsigned int hInstance,
    void *lpParam
);


5) At the very bottom of the page, there is a section titled "Function Information". The last item there is called "Unicode". Some functions don't have that Unicode item, but for those that do, it tells you that there are two different versions of the function. The difference between ANSI and Unicode is the type of string that you use. Aurora supports two ANSI strings: string (255 character length) and dstring (variable length, but not dynamic), and two unicode strings: wstring (255 word length) and dwstring (variable length, but again not dynamic). String literals are designated with quotes, and wstring literals are designated with quotes preceded by an L. It's up to you to use whichever you want, but since most of us tend to use the ANSI versions (unicode was recently added), I'll provide that declaration. It only requires a small change to the declaration.

import unsigned int CreateWindowEx alias "CreateWindowExA" (
    unsigned int dwExStyle,
    string lpClassName,
    string lpWindowName,
    unsigned int dwStyle,
    int x,
    int y,
    int nWidth,
    int nHeight,
    unsigned int hWndParent,
    unsigned int hMenu,
    unsigned int hInstance,
    void *lpParam
);


I hope that helps you.
Title: Re: a request
Post by: kryton9 on June 09, 2006, 02:07:26 PM
Parker, wow that was so fast and I just read through it really well presented. Now I will go in and really try to digest it by doing it all with your great help. Thanks so much!!!

Edited: (added this part after reading your tutorial a couple of times.)

First off this is going to be immensly helpful, thanks so much!!!
Hate to be so ignorant, but could you write a simple Aurora program using that declared function. I know I could probably go through and read other things on declarations but seeing it all with the same code will help me understand it so much more.

Also, does the declaration go in the source file or in an include file, I am confused on those decisions.

Do I need to put the dll in the same folder as the source code? Or do we just assume everyone has those dll's in windows system folders?

Thanks so much again!!!
Title: Re: a request
Post by: Ionic Wind Support Team on June 09, 2006, 02:15:52 PM
Quote
From what I can tell, all the api stuff is in a dll somewhere. How do you first of all know where to look? I do a search and MSDN brings up numerous functions that all seem the same to me.

MSDN can be a bit daunting, and they seem to make it harder to navigate every month, but here is a link that will get you to catagorized development guides:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnanchor/html/devguides.asp

And further down you can list functions by category

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winprog/winprog/functions_by_category.asp

Paul.
Title: Re: a request
Post by: kryton9 on June 09, 2006, 02:19:29 PM
Thanks Paul for the links, now with Parkers tutorial, your great tutorials that puddytat made into pdfs, I think I am going to really start delving into Aurora finally. I am really excited!!

I am also going to post into the 3d topic area something relating to all of this. Thanks again you guys, great community and support!!!
Title: Re: a request
Post by: Bruce Peaslee on June 09, 2006, 03:54:52 PM
Thanks, Paul. Even for someone like me who fools himself about his level of competance in this area, the links are useful.
Title: Re: a request
Post by: Ionic Wind Support Team on June 09, 2006, 04:04:41 PM
Quote from: kryton9 on June 09, 2006, 02:07:26 PM
Edited: (added this part after reading your tutorial a couple of times.)

First off this is going to be immensly helpful, thanks so much!!!
Hate to be so ignorant, but could you write a simple Aurora program using that declared function. I know I could probably go through and read other things on declarations but seeing it all with the same code will help me understand it so much more.

Also, does the declaration go in the source file or in an include file, I am confused on those decisions.

Do I need to put the dll in the same folder as the source code? Or do we just assume everyone has those dll's in windows system folders?

Thanks so much again!!!

You never include the windows API DLL's with your program.  Just declare the functions you need and go.

Whether you put them in an include file or not is entirely up to you.
Title: Re: a request
Post by: Parker on June 09, 2006, 04:30:00 PM
Why didn't anyone tell me about those pages before ??? ;D
Title: Re: a request
Post by: kryton9 on June 10, 2006, 12:01:07 AM
Is the great tutorial wrote to answer my request, is that considered a wrapper?

Title: Re: a request
Post by: Ionic Wind Support Team on June 10, 2006, 12:26:37 AM
?  If your refering to Parker's reply then no.  It is an API function declaration.  You use the function, the compiler calls it straight from the DLL.

A wrapper is usually something written to use code from one language into another.
Title: Re: a request
Post by: kryton9 on July 22, 2006, 11:11:41 PM
My Grey Matter must be gone. I have been reading and looking at lots of stuff, but when I sit down to do something.. I get no where.

Without using the Dialog Editor, can someone just write a simple hello world example that is in a window (not console, as can understand that example :) )
With a standard window with the minimize, maximize and close button and also an Exit and OK button in the window. Perhaps if OK is pressed it
will say something like the OK button has been pushed. And the Exit button to end the program.

With a simple windows program to start with I might find the foundation to work from. Sorry to be such a goof, but like I said I am not getting anywere.

I tried running Bruce's skeleton, header and forgot the name of the other file and they all gave errors on compiling. I thought I could use those, but with the errors
didn't see what could be the problem. THanks.
Title: Re: a request
Post by: Ionic Wind Support Team on July 22, 2006, 11:48:52 PM
There are tools to help you.  If your using controls in a window you have two choices...figure out where to place them or use the dialog editor to get the size and dimensions. 

If your using a standard window then you have to decide whether you want the window to be sizeable or not.  If you have controls in that window then sizing should probably not be allowed.

Here are some steps using the available tools

1. Open class maker (from the tools menu).
2. Double click on "CWindow". 
3. Type in a name for your derived class.  Call it "MyWindow" for instance.
4. In the left pane are all of the "OnXXXX" message handlers your window can process.  Click on "OnCreate" and holding down the CTRL key select "OnClose" and "OnControl". 
5. Click the ">>" button.  This copies the methods your class will use to the right pane.
6. Click the "Generate" button. Class maker will let you know the source was copied to the clipboard.
7. Open a new source window and paste it in.  It looks like this:


//MyWindow definition
class MyWindow : CWindow
{
declare MyWindow();
declare _MyWindow();
declare virtual OnClose(),int;
declare virtual OnControl(int nID, int nNotifyCode, unsigned int hControl),int;
declare virtual OnCreate(),int;
}

//MyWindow Implementation
MyWindow::MyWindow()
{
}

MyWindow::_MyWindow()
{
}

MyWindow::OnClose(),int
{
return 0;
}

MyWindow::OnControl(int nID, int nNotifyCode, unsigned int hControl),int
{
return 0;
}

MyWindow::OnCreate(),int
{
return 0;
}


8. Close the class maker.

What you just did is create a minimal window class that can be created and shown.  It doesn't do anything yet.

9. Edit the OnClose method so it looks like this:


MyWindow::OnClose(),int
{
Destroy();
return 0;
}


What that does is tell the window to destroy (close) itself when the close button is pressed.

10. Open the dialog/GUI editor.  We are only going to use it to figure out where some controls should be placed in the window. Make the size of the template 300 x 150.  If you look in the status bar of the IDE when sizing controls and the template it will show you the current size. 

11. Place two button controls on the template, OK and Exit.  Put them where you like. Click on the source gen button and select "Open in new window".  We are just going to cut and paste from it.

12.  Select and copy the two "AddControl" lines.  Paste them into the "OnCreate" method and remove the "d1." before each line.  Now the OnCreate handler should look like this:


MyWindow::OnCreate(),int
{
AddControl(CTBUTTON,"OK",36,111,70,20,0x5000000B,0x0,1);
AddControl(CTBUTTON,"Exit",194,111,70,20,0x5000000B,0x0,2);
return 0;
}


Now what you have is a window class that will show two buttons and responds to the close button.  A few more steps and we will be done.

13. Edit the OnControl handler to respond to the two controls.  A simple select satement will do.


MyWindow::OnControl(int nID, int nNotifyCode, unsigned int hControl),int
{
select nID
{
case 1: //The OK button
if(nNotifyCode = 0)
MessageBox(this,"OK Pressed","Info");
case 2: //The exit button
if(nNotifyCode = 0)
Destroy();
}
return 0;
}


14. Now for the last step.  Create the programs 'main' subroutine to open the window and wait for stuff to happen.  When we used the dialog editor to position the controls we picked a template size of 300 x 150.  Since the size of a window is slightly different than a dialog the controls won't fit vertically at the bottom.  I find it's easier to just increase the size of a window to accomodate then fiddle with the controls positions.

You need to tell the window what style it will have when creating.  The common ones are:

AWS_VISIBLE - The window can be seen
AWS_SYSMENU - The window has a close/min/max buttons
AWS_CAPTION - The window has a title bar

We will also add:

AWS_MINIMIZEBOX - The minimize box is enabled
AWS_CENTERED - The window is centered on creation.

Here is the main function:


global sub main()
{
MyWindow win;
win.Create(0,0,300,170,AWS_VISIBLE|AWS_CENTERED|AWS_MINIMIZEBOX|AWS_CAPTION|AWS_SYSMENU,0,"Test",0);
do
{
wait();
} until( !win.IsValid() );
}


So all you do is define a variable of your class, call it's Create function, and wait for messages.  The IsValid method returns true if the window is still open, and false otherwise.  We will make one more change.  Print the text "Hello World" in the window, I'll also add the style AWS_AUTODRAW which will remember the contents of the window when it's been covered up or minimized/restored.

The complete program here:


//MyWindow definition
class MyWindow : CWindow
{
declare MyWindow();
declare _MyWindow();
declare virtual OnClose(),int;
declare virtual OnControl(int nID, int nNotifyCode, unsigned int hControl),int;
declare virtual OnCreate(),int;
}

//MyWindow Implementation
MyWindow::MyWindow()
{
}

MyWindow::_MyWindow()
{
}

MyWindow::OnClose(),int
{
Destroy();
return 0;
}

MyWindow::OnControl(int nID, int nNotifyCode, unsigned int hControl),int
{
select nID
{
case 1: //The OK button
if(nNotifyCode = 0)
MessageBox(this,"OK Pressed","Info");
case 2: //The Exit button
if(nNotifyCode = 0)
Destroy();
}
return 0;
}

MyWindow::OnCreate(),int
{
AddControl(CTBUTTON,"OK",36,111,70,20,0x5000000B,0x0,1);
AddControl(CTBUTTON,"Exit",194,111,70,20,0x5000000B,0x0,2);
return 0;
}

global sub main()
{
MyWindow win;
win.Create(0,0,300,170,AWS_VISIBLE|AWS_CENTERED|AWS_MINIMIZEBOX|AWS_CAPTION|AWS_SYSMENU|AWS_AUTODRAW,0,"Test",0);
win.WriteText(0,10,"Hello World");
do
{
wait();
} until !win.IsValid();
}


Hope that is what you are after.  I know you didn't want to use the dialog editor. But it's a lot simpler than figuring out control sizes in your head, and that is all we used it for.  Unless you really want to sit down with a calculator and some paper first ;)

If you don't want to use class maker then you can use the skeleton help file (Aurora users guide from the help menu).  Open "Programmer's Reference" then "Classes" then "CWindow" then "Methods".  You'll see the same OnXXX handlers listed there which you can cut and paste from. 

Paul.


Title: Re: a request
Post by: Doc on July 23, 2006, 08:04:41 AM
Hope you add that to your tutorial or user's guide Paul.

I don't yet spend a lot of time with Aurora and to be honest, had completely forgotten about the class maker tool.
It's a good reminder and tutorial about using a valuable asset. :)

-Doc-
Title: Re: a request
Post by: Ionic Wind Support Team on July 23, 2006, 08:11:01 AM
Glad you liked it.  I use ClassMaker all the time since I don't have to wory about typos or cutting and pasting from gui.inc
Title: Re: a request
Post by: Vikki on July 23, 2006, 08:46:11 AM
Very nice tutorials. They need to go into the help file in an appendix or something!ÂÃ,  ;)
Title: Re: a request
Post by: Kale on July 23, 2006, 09:51:24 AM
I've found the two most used references for me when it comes to using the WinAPI are these:

Win32 API Reference
http://www.garyw.uklinux.net/pb/WIN32.zip

APIGuide
http://www.allapi.net/agnet/apiguide.shtml

Both provide a more focused reference for the API and after checking these two out you can always trawl through the MSDN later. ;)
Title: Re: a request
Post by: kryton9 on July 23, 2006, 12:29:11 PM
Paul, Oh wow amazing. Will try it out today and go in depth to really understand. Thanks!! I have nothing against using tools, I played with the dialog editor and loved it, but I couldn't really follow what was going with the code. This will help immensly

Also had an idea to make Aurora easier. When compiling instead of selecting if it is windows, console or dll. Why not just name the file extention in a way that the compiler knows. Also this way the users can know looking at the example folder what sort of example they are looking at.

So it might be like:

example.srcw

example.srcc

example.srcd
Title: Re: a request
Post by: kryton9 on July 23, 2006, 01:02:42 PM
THanks Kale, anything to help with API will come in handy. Those links Paul had given and now your links and downloads. thanks.
Title: Re: a request
Post by: kryton9 on July 23, 2006, 01:25:09 PM
Ok went through the wonderful tutorial a few times and the lightbulbs are going on :)

In first looking, I was confused about the writetext and isvalid method. But when I looked in the help section in Aurora and under programmers refererence:classes: cwindow
I found those methods along with a ton of others. So I assume we can use those even though they were not declared in our class.

Now onclose is in there as a method in the help files. Why did it have to be declared in our class? Why couldn't we just use it like we could win.writetext() as win.onclose() or win.onclose(destroy()) without declaring it?

Why were they declared as virtual is another aspect, I don't understand?
Title: Re: a request
Post by: Ionic Wind Support Team on July 23, 2006, 01:51:25 PM
OnClose is a virtual function. It is called by windows when the WM_CLOSE message is sent.  The method exists in the CWindow class but does nothing.

So you have to override it in your class if you want to process the message.
Title: Re: a request
Post by: kryton9 on July 23, 2006, 02:13:00 PM
ok, just to make sure I understand. If you over ride an existing method in a class, it is declared as virtual. Otherwise no need to declare it, just use it as with writetext().
And of course if I create a new method it would be delcared as a regular method, what about overloaded methods? I was reading about them on that site you had mentioned.

If I didn't declare onclose as virtual, would it have then become an overloaded method?
Title: Re: a request
Post by: kryton9 on July 23, 2006, 02:37:40 PM
Testing and decided to recreate the window example with the dialog editor.
I had placed a static text "hello world" and it worked fine. I then commented that line
and from looking at cdialog it looked like it was derived from cwindow, so I thought I could use
writetext().
  How would I get the image inside the img blocks?

It gives no errors, but it doesn't seem to work. So confused on where I went wrong. I also couldn't use destroy() for button 2 which would be the cancel button?

#define BUTTON_1 1
#define BUTTON_2 2
#define STATIC_3 3
class dlg:CDialog
{
declare OnInitDialog(),int;
declare OnClose(),int;
declare OnControl(int nID, int nNotifyCode, unsigned int hControl),int;
}

global sub main()
{
dlg d1;
d1.Create(0,0,300,202,0x80CB0080,0,"Test",0);
d1.AddControl(CTBUTTON,"OK",24,157,70,20,0x5000000B,0x0,BUTTON_1);
d1.AddControl(CTBUTTON,"Cancel",165,156,70,20,0x5000000B,0x0,BUTTON_2);
//d1.AddControl(CTSTATIC,"Hello World",18,13,70,20,0x5000010B,0x0,STATIC_3);
d1.WriteText(0,10,"Hello World");

d1.DoModal();
return 0;
}

dlg::OnClose(),int
{
CloseDialog(1);
return true;
}

dlg::OnInitDialog(),int
{
/* Initialize any controls here */
CenterWindow();
return true;
}

dlg::OnControl(int nID, int nNotifyCode, unsigned int hControl),int
{
select nID
{
case BUTTON_1:
if(nNotifyCode = 0)
{
/*button clicked*/
MessageBox(this,"OK Pressed","Info");
}
case BUTTON_2:
if(nNotifyCode = 0)
{
/*button clicked*/
CloseDialog(1); // destroy(); didn't work
}
}
return true;
}

Title: Re: a request
Post by: Ionic Wind Support Team on July 23, 2006, 02:59:55 PM
A dialog is a window but is meant to be a container for controls.  You can have text directly in a dialog, but you have to do it in response to the OnPaint handler.

A virtual method is always virtual.  Meaning if the base class declares it as virtual then it doesn't matter if you leave off the 'virtual' keyword in the derived class.  The compiler knows.
Title: Re: a request
Post by: kryton9 on July 23, 2006, 03:23:02 PM
How does a newbie to oop like me know what to use. CDialog is derived from CWindow, am I right about that? And if so, why can't I use that method or better yet, how would I know I couldn't use it and be doing something wrong. And then, how would I know to use OnPaint instead of writetext()?

Is there something else I could read to help me understand all of this. I hate to be posting such stupid questions, but to someone from this end-- stuff that is very confusing :)
Title: Re: a request
Post by: Ionic Wind Support Team on July 23, 2006, 03:56:53 PM
You can use WriteText. 

CWindow has a specially designed style called AWS_AUTODRAW.  Which is a functionality that I designed into it, not a part of windows.  Using that style anything you draw onto the client area is stored in an internal bitmap.  If your familiar with IBasic it works the same way.

A normal window, created with the API, or say C++, doesn't keep a copy of what you draw and you have to refresh the drawing over and over in response to WM_PAINT.  Which is the OnPaint handler in Aurora.

If you read any good Windows programming book you should have a better handle on the topic.  Dialogs are meant to be containers for controls, and they contain special message processing for things like the default button, tabbing between controls, processing ESC by sending the ID of 2 to OnControl, etc.  That's not an Aurora thing, it is a Windows thing.

Other than that have patience.  Documentation will come with time.

Paul.
Title: Re: a request
Post by: kryton9 on July 23, 2006, 04:01:52 PM
Yes, looking at the help in Aurora, the skeleton that is there, it is clear that once all that info is filled in, all of this will be a lot easier to pick up.

I was just excited when I thought oh, it is derived from this class and I then get access to all of those methonds. THen I could see why you are all excited about
classes. But then, sort of stumbled and got lost.

But with the great window example, and all your other examples now. Hopefully I can fill in the gaps. I have a start and an end to look at and lots of great help here.

Thanks again. I know it will all click and I will stop looking back at the old ways :)
Title: Re: a request
Post by: Ionic Wind Support Team on July 23, 2006, 04:13:10 PM
Well you are right.  You have access to all of the base class methods from a derived class.  Whether they are meant to function in the derived class is another matter.  99% of the time you can, or can use them after following certain conditions.  Hate to be vague here but it depends on the base class in question.

Title: Re: a request
Post by: kryton9 on July 23, 2006, 04:21:53 PM
Thanks, I am understanding it slowly. This example helped as I can really experiment with it and compare it with the dialog and being rather minimal apps it is easy to understand and to build from. Now I understand where some of the methods were coming from when not declared and I am understanding how the skeleton help is already helpful and what I see there now is making more sense. I couldn't see in the help where the CWindow methods were Virtual methods?


Of course that Class Tool, I had no idea what to do with that. THat is a wonderful tool as is the dialog editor. I also understand the coolness of having include files and being able to break the source up into classes and things. I can see how all of that will make life wonderful on big projects.

I have a question about all of that, but will post in Sapero's windows include topic.
Title: Re: a request
Post by: Ionic Wind Support Team on July 23, 2006, 04:49:29 PM
The template Larry uses for the help file calls it an "overridable" method.  Which is the same as a virtual method.

For example the OnCreate description says:

Quote
Event Handler Method (overrideable)

Meaning it is called in response to a window message and is a virtual method. 
Title: Re: a request
Post by: kryton9 on July 23, 2006, 05:33:09 PM
Ah ahh, making more and more sense. THanks!!