January 19, 2021, 02:28:25 am

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


a request

Started by kryton9, June 09, 2006, 11:34:38 am

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

kryton9

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.

Parker

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.

kryton9

June 09, 2006, 02:07:26 pm #2 Last Edit: June 09, 2006, 02:17:22 pm by kryton9
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!!!

Ionic Wind Support Team

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.
Ionic Wind Support Team

kryton9

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!!!

Bruce Peaslee

Thanks, Paul. Even for someone like me who fools himself about his level of competance in this area, the links are useful.
Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

Ionic Wind Support Team

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.
Ionic Wind Support Team

Parker

Why didn't anyone tell me about those pages before ??? ;D

kryton9

Is the great tutorial wrote to answer my request, is that considered a wrapper?


Ionic Wind Support Team

?  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.
Ionic Wind Support Team

kryton9

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.

Ionic Wind Support Team

July 22, 2006, 11:48:52 pm #11 Last Edit: July 23, 2006, 12:00:50 am by Paul Turley
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:

Code Select

//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:

Code Select

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:

Code Select

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.

Code Select

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:

Code Select

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:

Code Select

//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.


Ionic Wind Support Team

Doc

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-

Ionic Wind Support Team

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
Ionic Wind Support Team

Vikki

July 23, 2006, 08:46:11 am #14 Last Edit: July 23, 2006, 08:58:26 am by Vikki
Very nice tutorials. They need to go into the help file in an appendix or something!ÂÃ,  ;)

Kale

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. ;)

kryton9

July 23, 2006, 12:29:11 pm #16 Last Edit: July 23, 2006, 01:01:30 pm by kryton9
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

kryton9

THanks Kale, anything to help with API will come in handy. Those links Paul had given and now your links and downloads. thanks.

kryton9

July 23, 2006, 01:25:09 pm #18 Last Edit: July 23, 2006, 01:29:10 pm by kryton9
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?

Ionic Wind Support Team

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.
Ionic Wind Support Team

kryton9

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?

kryton9

July 23, 2006, 02:37:40 pm #21 Last Edit: July 23, 2006, 02:51:07 pm by kryton9
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?

Code Select
#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;
}

Ionic Wind Support Team

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.
Ionic Wind Support Team

kryton9

July 23, 2006, 03:23:02 pm #23 Last Edit: July 23, 2006, 03:58:14 pm by kryton9
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 :)

Ionic Wind Support Team

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.
Ionic Wind Support Team