Hello,
i have this function that open a window with a menu:
struct Window *open_window (struct Screen *scr,const char *title,long x,long y,long w,long h,struct NewMenu *newmenu,struct VisualInfo *vi,struct Menu **menuptr)
{
struct Menu *menu = NULL;
struct Window *win;
if ((win = OpenWindowTags (NULL,
WA_CustomScreen,scr,
WA_Title,title,
WA_Left,x,
WA_Top,y,
WA_Width,w,
WA_Height,h,
WA_Flags,WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEGADGET | WFLG_SIZEBBOTTOM | WFLG_ACTIVATE | WFLG_NEWLOOKMENUS | WFLG_NOCAREREFRESH,
WA_IDCMP,IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_MENUPICK,
WA_MaxWidth,scr->Width,
WA_MaxHeight,scr->Height,
TAG_END)))
{
if (vi)
if (menu = CreateMenusA (newmenu,NULL))
if (LayoutMenus (menu,vi,GTMN_NewLookMenus,TRUE,TAG_END))
SetMenuStrip (win,menu);
}
*menuptr = menu;
return (win);
}
how would you change this function to reflect the modern approach described by trixie?
thank you very much
Here's how i changed the function:
Object *open_window (struct Screen *scr,const char *title,long x,long y,long w,long h,Object *tbimg[],int TB_MAX, struct NewMenu *newmenu,struct VisualInfo *vi,struct Menu **menuptr)
{
Object *winobj;
if ((winobj = NewObject (WindowClass,NULL,
WA_PubScreen, scr,
WA_Title, "ReAction Tool Bar",
WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEBBOTTOM | WFLG_SIZEGADGET | WFLG_ACTIVATE,
WA_IDCMP, IDCMP_VANILLAKEY | IDCMP_INTUITICKS,
WA_Width, scr->Width * 6 / 10,
WA_Height, scr->Height * 4 / 10,
WINDOW_NewMenu,newmenu,
WINDOW_BackFillName, "Sys:Prefs/Presets/Patterns/Chalk/ChalkBlue.brush",
WINDOW_Position, WPOS_CENTERSCREEN,
WINDOW_ParentGroup, NewObject (LayoutClass,NULL,
LAYOUT_Orientation,LAYOUT_ORIENT_VERT,
LAYOUT_SpaceOuter, TRUE,
LAYOUT_AddChild,ToolBar(tbimg,TB_MAX),
LAYOUT_AddChild,NewObject (LayoutClass,NULL,
TAG_END),
LAYOUT_AddChild,NewObject (LayoutClass,NULL,
LAYOUT_SpaceOuter, FALSE,
LAYOUT_FixedVert, FALSE,
LAYOUT_EvenSize, TRUE,
LAYOUT_AddChild, NewObject (ButtonClass,NULL,
GA_ID, GID_OK,
GA_Text, "Ok",
GA_RelVerify, TRUE,
TAG_END),
LAYOUT_AddChild, NewObject (ButtonClass,NULL,
GA_ID, GID_CANCEL,
GA_Text, "Cancel",
GA_RelVerify, TRUE,
TAG_END),
TAG_END),
TAG_END),
TAG_END)))
{
//if (vi)
//if (menu = CreateMenusA (newmenu,NULL))
//if (LayoutMenus (menu,vi,GTMN_NewLookMenus,TRUE,TAG_END))
//SetMenuStrip (win,menu);
//}
//*menuptr = menu;
return (winobj);
}
}
since i don't use the VisualInfo struct anymore in this function, i guess i should remove it from the parameters passed to the function. Or could be usefull to keep for other reason?
these parameters are not necessary too:
const char *title,long x,long y,long w,long h, struct Menu **menuptr
@AmigaBlitter
If you're using WINDOW_NewMenu, you don't need to LayoutMenus(), so you don't need the VisualInfo - the Window Class handles menu creation and layouting itself.
However, be warned that menus created via WINDOW_NewMenu have a side-effect. Any opening (re-opening, uniconifying) of the window will reset the menu strip to the default state as described by your NewMenu structure. Thus, the programmer is responsible for storing the menu state before closing the window, and for restoring the state when the window reopens.
So in effect, until Window Class is changed to keep the menu state for closed windows, you may find that WINDOW_NewMenu actually gives you more work than it saves ;-)
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
@AmigaBlitter
Look at your function again.
What happens if the NewObject() call fails for some reason? Your function will be left without a valid return value, because you only return in case of success. You need to change your function to something like
Also note that your function is called open_window() but it doesn't really open the window - it just creates the window object. Such naming does not contribute to a clear and understandable code.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
@trixie
Thank you for the info.
Always using the new methods, how to add a string and a label object?
LAYOUT_AddChild, NewObject (ButtonClass,NULL,
GA_ID, GID_OK,
GA_Text, "Ok",
GA_RelVerify, TRUE,
TAG_END),
This add a button, but a can't find clear references for string, label and other objects via new methods.
Thank you
@AmigaBlitter
LAYOUT_AddChild, NewObject (StringClass,NULL,
TAG_END),
CHILD_Label, NewObject (LabelClass,NULL,
LABEL_Text, "Label",
TAG_END),
Trixie,
You gave a good advice when you asked to verifiy if the window pointer is NULL before returning it.
I have a question for you. Why do all programmers use newobject in window instantation ? What happens if newobject could not be created ? Do Intuition create nevertheless the window ?
Don't we should create all newobjects before creating the window ?
@salass00
thank you
This is what I did before asking, but i've got strange behaviour.
The program compiled OK, but i had nothing on screen (i mean no screen, window and gadgets), then, after few seconds, the OS frozen
Edit: sorry, i've made two mistake. one of this is fundamental: i forgoto to open the class, first :P
It works now.
Thank you
Now, simply adding the string in that way
LAYOUT_AddChild, NewObject (StringClass,NULL,
TAG_END),
it is possible to get string events? Or should i give an identifier to the string?
@YesCop
It's just a matter of technique. If you instantiate the window object in one go together with the contents (i.e. the window's layout), and one of the NewObject() calls in the sequence fails, the window object will not get created (and I believe that Window Class disposes of the objects already created - but you'll have to ask Rigo about that, he maintains the class). Some programmers instantiatate the window and the layout objects separately and then pass the layout to the window object via WINDOW_Layout. But creating all objects individually and then joining them together would be too much of a hassle.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
@AmigaBlitter
You must use GA_ID and assign an identifier to be able to distinguish between events you receive from Intuition. There are plenty of examples that show this in the SDK/Examples/Reaction folder.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
Window.class only disposes of the WINDOW_Layout object, any objects attached to this are then disposed of by layout.gadget and so on until all the objects are disposed of.
@trixie
"You must use GA_ID"....
the following code comes from the string reaction example. As you can see it uses RA_HandleImput... I don't remember where i read to avoid all RA_. Is this related to old methods?
Sorry for the another thread i opened for the string events, btw.
@AmigaBlitter
No. RA_HandleInput is a macro, which expands to the WM_HANDLEINPUT method call. See section 4.4 of my tutorial on ReAction programming.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
Yeah! I read it there:
"If you have copied the input handling routine from such a source, make sure to replace the macro with the corresponding method call:"
while ( (result = IIntuition->IDoMethod(winObj, WM_HANDLEINPUT, &code)) != WMHI_LASTMSG )
{
...
}
thank you
@trixie
Can't intercept the string events. This is the loop code:
What i've forgot this time?
Solved:
I've add the following:
GA_RelVerify, TRUE,
GA_TabCycle, TRUE,
and now the event get intercepted
Btw, how to refer to the string and get the content of the string?
if i do:
struct Gadget *gadgets[GID_LAST];
printf( "Contents: %s\n", ((struct StringInfo *)(gadgets[GID_STRING1]->SpecialInfo))->Buffer);
the program crash and the system freeze soon after
thank you
@AmigaBlitter
Yes, all Intuition gadgets whose events you want to listen to must have this set.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
Thank you Danjiel,
i will try as soon as back home.
As for the freeze problem, i should check if i have disposed all the objects, or disposing the window object dispose all the children too?
@AmigaBlitter
Disposing of the window object will also dispose of all children objects attached to it.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
@trixie
Trying to get the string content i get:
error: 'struct IntuitionIFace' has no member named 'IIntuition'
@AmigaBlitter
Looks like you're compiling your code with
#define __USE_INLINE__
In that case don't use "IIntuition->" or other interface names in function calls.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
I use __USE_INLINE__ as switch on the command line. What should i use instead?
Btw, omitting this switch cause me to get tons of warning and undefined reference for my actual code as follow:
(.text+0xd08): undefined reference to `Printf'
(.text+0xd24): undefined reference to `CreateBackFillHook'
(.text+0xd64): undefined reference to `OpenScreenTags'
(.text+0xd90): undefined reference to `GetVisualInfoA'
(.text+0xfb0): undefined reference to `DoMethod'
(.text+0xfdc): undefined reference to `DoMethod'
(.text+0x100c): undefined reference to `GetAttr'
(.text+0x1028): undefined reference to `Wait'
(.text+0x11ac): undefined reference to `Printf'
(.text+0x11c4): undefined reference to `Printf'
(.text+0x11ec): undefined reference to `GetAttr'
(.text+0x1214): undefined reference to `ItemAddress'
(.text+0x1244): undefined reference to `Printf'
(.text+0x1264): undefined reference to `ItemAddress'
(.text+0x12b8): undefined reference to `DoMethod'
(.text+0x12e8): undefined reference to `DisposeObject'
(.text+0x12f4): undefined reference to `DisposeObject'
(.text+0x1344): undefined reference to `DisposeObject'
(.text+0x1380): undefined reference to `FreeVisualInfo'
(.text+0x139c): undefined reference to `CloseScreen'
(.text+0x13a8): undefined reference to `DeleteBackFillHook'
@AmigaBlitter
Read what I'm writing and you'll be fine :)
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
"In that case don't use "IIntuition->" or other interface names in function calls."
Sorry, but i'm not an expert.
:(
@AmigaBlitter
Never mind.
You'll use
IIntuition->GetAttrs()
in code compiled without __USE_INLINE__. The "IIntuition->" prefix refers to the name of the Intuition library interface. As of OS4.x, Amiga libraries can have multiple interfaces ("function groups") inside them, so the interface name specifies where the function comes from. This is what most new code should use.Older code can be compiled with the __USE_INLINE__ switch. In that case, functions are used without interface names, i.e.
GetAttrs()
in your particular case.AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
Hi,
thank you for your patience. I know i'm boring you. Sorry for this.
I changed all the prefix in the following way:
IDataTypes->NewDTObject
IIntuition->IDoMethod
IDataTypes->GetDTAttrs
ILayers->SetBackFillHookAttrs
IDataTypes->DisposeDTObject
IIntuition->OpenWindowTags
IIntuition->CloseWindow
IDOS->AddPart
IIntuition->NewObject
IIntuition->GetAttr
IIntuition->GetAttrs
IIntuition->SetAttrs
IDOS->Printf
ILayers->CreateBackFillHook
IIntuition->OpenScreenTags
IGadTools->GetVisualInfoA
IExec->Wait
IIntuition->ItemAddress
IGadTools->FreeVisualInfo
IIntuition->CloseScreen
IIntuition->DeleteBackFillHook
i still have this problem:
warning: passing argument 2 of 'IIntuition->GetAttrs' makes pointer from integer without a cast
error: 'struct IntuitionIFace' has no member named 'DeleteBackFillHook
@AmigaBlitter
It's no trouble. We all were beginners at some point.
You are passing a wrong or un-cast argument to GetAttrs(). You need to show me the actual function call and how its parameters are declared.
DeleteBackFillHook() is a function in layers.library (not Intuition), so you need to open layers library and interface, and then change your code to use ILayers->DeleteBackFillHook().
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
Thank you
I used the Layers->DeleteBackFillHook() and now it's ok and compile (my mistake, sorry)
Here's is the code related to the warning message: "warning: passing argument 2 of 'IIntuition->GetAttrs' makes pointer from integer without a cast"
IIntuition->GetAttrs(GID_STRING1, STRINGA_TextVal, (uint32 *)&stringContents, TAG_DONE);
Note: the code get compiled, but as soon as i test the string gadget pressing enter, i get a DSI error
@AmigaBlitter
It's because in the first argument, you are passing a numeric identifier, not an actual object pointer. Looking at your GUI definition in post #2, I see that you are adding new objects via LAYOUT_AddChild but without storing the resulting object pointers in particular variables. Having no variables = having no way to manipulate your objects.
Let's say your GUI will have three gadgets: a string and two buttons (OK and Cancel). First you need to define a set of identifiers for your gadget objects. They are just a sequence of numbers:
Then you need to declare variables to keep your object pointers in. If there are more gadgets than one, we normally declare a field of variables, whose particular items (objects) will subsequently be referred to using the IDs above:
Object *gadgets[GID_LAST];
When creating new objects and adding them to the layout, you must assign the resulting object pointer to the particular variable (field item), like this:
Now to make your GetAttr() call work, you need to pass the pointer to the particular string object:
IIntuition->GetAttrs(gadgets[GID_STRING], STRINGA_TextVal, (uint32 *)&stringContents, TAG_DONE);
Hope it's clearer now. But you should really have a look at some ReAction examples in the SDK/Examples directory - they will give you a lot of insight.
AmigaOne X5000-020 / 2GB RAM / Sapphire Pulse Radeon RX 560 / AmigaOS 4.1 Final Edition Update 2
Since only one attribute is being queried it would be simpler to just use GetAttr():
IIntuition->GetAttr(STRINGA_TextVal, gadgets[GID_STRING], (uint32 *)&stringContents);
Thank you Danjiel for the explanations. Now i have understand better
Just want to strike a blow for me, cause i completely messed up old and new methods, macro and no macro, Boopsi and so on...
Thank you salass00 too and to Hans de Ruiter
The code now works!!!
@trixie
LAYOUT_AddChild, gadgets[GID_STRING] = IIntuition->NewObject(LayoutClass, NULL,
GA_ID, GID_STRING,
GA_RelVerify, TRUE,
GA_TabCycle, TRUE,
TAG_END),
Did you mean StringClass instead of LayoutClass, didn't you?
Pages