About
GeUserArea is the base class for all gadgets that can be displayed in a GeDialog. A new gadget is created by implementing a subclass of GeUserArea. Such a gadget manages user interaction and draws the gadget interface in the GUI.
- Note
- GeUserArea based classes can only be used with a GeDialog or GeDialog based classes. To create a custom GUI element that can be used in the Attribute Manager one must implement a CustomGuiData / iCustomGui based plugin.
Allocation
An instance of a GeUserArea based class is typically stored as a member of the parent GeDialog. It is added to the dialog layout using:
- GeDialog::AddUserArea(): Adds a user area to the dialog layout.
- GeDialog::AttachUserArea(): Connects the user area gadget with the actual user area instance.
See GeDialog Manual.
private:
MyUserArea _geUserArea;
public:
{
SetTitle("GeUserArea Dialog"_s);
C4DGadget*
const userAreaGadget = this->AddUserArea(100,
BFH_LEFT, 400, 100);
if (userAreaGadget)
this->AttachUserArea(_geUserArea, userAreaGadget);
maxon::Bool Bool
Definition: ge_sys_math.h:46
@ BFH_LEFT
Aligned to the left. 1<<3.
Definition: gui.h:312
The parent dialog is accessible with:
- GeUserArea::GetDialog(): Returns the parent GeDialog.
GeUserArea Based Classes
A custom user area is created by implementing a subclass of GeUserArea. This subclass can implement different virtual functions that define the behaviour of the gadget.
The user area is initiated with:
- GeUserArea::Init(): Called once when the user area is initialized.
- GeUserArea::InitValues(): Initiates the values displayed with the user area.
{
this->SetTimer(500);
return true;
}
The size of the user area is handled with:
- GeUserArea::GetMinSize(): Defines the minimum size of the user area.
- GeUserArea::Sized(): Called when the user area is resized.
{
w = 400;
h = 100;
return true;
}
{
_width = w;
_height = h;
}
maxon::Int32 Int32
Definition: ge_sys_math.h:51
Different messages are sent to a user area:
{
{
{
return true;
}
}
}
PyObject PyObject * result
Definition: abstract.h:43
@ BFM_GETCURSORINFO
Definition: gui.h:561
@ RESULT_BUBBLEHELP
String Bubble help text.
Definition: gui.h:565
@ RESULT_CURSOR
Int32 Mouse cursor: MOUSE
Definition: gui.h:564
static const Int32 MOUSE_POINT_HAND
Point hand cursor.
Definition: ge_prepass.h:2733
const char const char * msg
Definition: object.h:438
The primary purpose of a user area is to draw the actual user interface:
- GeUserArea::DrawMsg(): Called to draw the user area.
{
OffScreenOn();
SetClippingRegion(x1, y1, x2, y2);
DrawRectangle(x1, y1, x2, y2);
}
maxon::Vec3< maxon::Float64, 1 > Vector
Definition: ge_math.h:140
- Note
- To optimize the drawing call skip the redraw if only the focus has changed, see ::BFM_DRAW_REASON in Draw.
A user area can catch user interaction events:
- GeUserArea::InputEvent(): Called when an input event (keyboard, mouse) is received.
Bool InputEvent(
const BaseContainer&
msg)
{
{
{
Global2Local(&mx, &my);
ApplicationOutput(
"Mouse Event at " + String::IntToString(mx) +
" - " + String::IntToString(my));
return true;
}
}
return false;
}
@ BFM_INPUT_MOUSE
Mouse.
Definition: gui.h:711
@ BFM_INPUT_Y
Float Y value.
Definition: gui.h:729
@ BFM_INPUT_DEVICE
Int32 Device:
Definition: gui.h:710
@ BFM_INPUT_X
Float X value.
Definition: gui.h:728
#define ApplicationOutput(formatString,...)
Definition: debugdiagnostics.h:204
See also GeDialog Gadget Interaction.
Read-Only Properties
These properties can be read from a user area:
- GeUserArea::GetId(): Returns the ID of the user area.
- GeUserArea::GetWidth(): Returns the width of the user area.
- GeUserArea::GetHeight(): Returns the height of the user area.
- GeUserArea::IsEnabled(): Returns true if the user area is enabled.
- GeUserArea::IsR2L(): Returns true if the user area should be drawn in right-to-left layout mode (Arabic interface).
- GeUserArea::HasFocus(): Returns true if the user area has the focus.
SendParentMessage(action);
@ BFM_ACTION_ID
Int32 ID of the dialog element that triggered the action.
Definition: gui.h:747
@ BFM_ACTION
One of the child elements made any action:
Definition: gui.h:746
{
OffScreenOn();
SetClippingRegion(x1, y1, x2, y2);
if (this->HasFocus())
DrawSetPen(
Vector(0.0, 0.0, 1.0));
else
DrawSetPen(
Vector(0.0, 0.2, 0.8));
DrawRectangle(x1, y1, x2, y2);
}
Timer
A user area can use an internal timer that calls GeUserArea::Timer() periodically.
- GeUserArea::SetTimer(): Initializes the timer clock.
{
this->SetTimer(500);
return true;
}
void Timer(
const BaseContainer&
msg)
{
}
User Interaction
A user area can handle user interaction events by implementing GeUserArea::InputEvent(). The following functions are used to get more detailed information on the current event:
- GeUserArea::GetInputState(): Gets the current state of the given input device.
- GeUserArea::GetInputEvent(): Gets the next input event for the given device from the event queue.
- GeUserArea::KillEvents(): Flushes all events from the window message queue.
- GeUserArea::IsHotkeyDown(): Returns true if the given hotkey is pressed. see HOTKEYFLAGS.
A special operation is a mouse drag event inside the user area. Such a mouse drag is initiated in reaction to certain user interaction using these functions:
- GeUserArea::MouseDragStart(): Starts the mouse drag operation.
- GeUserArea::MouseDrag(): Polls the mouse during a drag.
- GeUserArea::MouseDragEnd(): Ends a mouse drag operation.
{
BaseContainer channels;
Global2Local(&startX, &startY);
{
break;
break;
if (deltaX != 0.0 || deltaY != 0.0)
}
MouseDragEnd();
return true;
}
PyArena _PyASTOptimizeState * state
Definition: compile.h:99
CONTINUE
Drag still in progress.
Definition: ge_prepass.h:2
DONTHIDEMOUSE
Show mouse pointer during drag.
Definition: ge_prepass.h:1
@ BFM_INPUT_MOUSELEFT
Left mouse button.
Definition: gui.h:716
@ BFM_INPUT_VALUE
Int32 Value of the input channel (true/false or a Int32 value, e.g. for scroll wheel data).
Definition: gui.h:726
@ BFM_INPUT_CHANNEL
Int32 Contains the key or mouse button. See also KEY.
Definition: gui.h:715
Bool GetInputState(Int32 askdevice, Int32 askchannel, BaseContainer &res)
maxon::Float Float
Definition: ge_sys_math.h:57
Drag and Drop
The user can drag and drop various elements onto a user area. The user area is informed about this event through messages sent to GeUserArea::Message(). These functions are used to react to those messages:
- GeUserArea::CheckDropArea(): Returns true if the drag event is over the user area.
- GeUserArea::GetDragPosition(): Gets the coordinates of the drag event.
- GeUserArea::GetDragObject(): Gets the object that is dragged.
- GeUserArea::SetDragDestination(): Sets the cursor that should be displayed. See MOUSE.
See also Drag and Drop.
{
if (!CheckDropArea(
msg,
true,
true))
break;
void* data = nullptr;
if (!GetDragObject(
msg, &
type, &data))
return false;
return false;
const AtomArray* const elements = static_cast<AtomArray*>(data);
if (!elements->GetIndex(0))
return false;
{
for (
Int32 i = 0;
i < elements->GetCount(); ++
i)
{
const C4DAtom*
const atom = elements->GetIndex(
i);
{
const BaseList2D*
const baselistObject =
static_cast<const BaseObject*
>(
atom);
}
}
}
else
{
}
return true;
}
Py_ssize_t i
Definition: abstract.h:645
#define atom
Definition: graminit.h:72
@ BFM_DRAG_FINISHED
Bool Drag finished.
Definition: gui.h:797
@ DRAGTYPE_ATOMARRAY
AtomArray.
Definition: gui.h:786
@ BFM_DRAGRECEIVE
Drag receive. (See DragAndDrop.)
Definition: gui.h:774
#define Tbaselist2d
2D list.
Definition: ge_prepass.h:995
PyObject ** type
Definition: pycore_pyerrors.h:34
It is also possible to start a drag and drop operation from a user area. This is typically done in reaction to some user interaction.
- GeUserArea::HandleMouseDrag(): Starts a drag and drop operation.
Bool InputEvent(
const BaseContainer&
msg)
{
{
{
return true;
}
}
return false;
}
@ DRAGTYPE_RGB
RGB color.
Definition: gui.h:788
Parent Message
A user area can send messages to its parent GeDialog. This is typically done to inform the dialog that some user interaction occurred and that the managed values changed.
- GeUserArea::SendParentMessage(): Sends a message to the parent dialog.
See GUI and Interaction Messages Manual.
SendParentMessage(action);
Drawing
Drawing Basics
The central task of a user area is to draw something to Cinema 4D's user interface. The drawing operations have to happen inside the GeUserArea::DrawMsg() function.
The drawing operation can be triggered with:
- GeUserArea::Redraw(): Forces the user area to redraw itself.
- GeUserArea::LayoutChanged(): Informs Cinema 4D that the user area has new dimensions. This will result in a redraw.
Drawing Operations
The following functions can be used to draw inside the canvas provided by the user area. For more advanced drawing operations one can use a GeClipMap and GeUserArea::DrawBitmap().
The color and opacity settings are handled with:
- GeUserArea::GetColorRGB(): Gets the color value for the given color ID. See
c4d_colors.h
.
- GeUserArea::DrawSetPen(): Sets the currently used drawing color.
- GeUserArea::DrawSetOpacity(): Sets the opacity used in the following drawing operations.
DrawRectangle(x1, y1, x2, y2);
#define DRAWTEXT_HALIGN_LEFT
Align to the left.
Definition: c4d_gui.h:189
Different styles used with various drawing functions are (::LINESTYLE):
- LINESTYLE::NORMAL
- LINESTYLE::DOTTED
- LINESTYLE::DASHED
- LINESTYLE::DASHED_INV
These functions draw primitive shapes:
- GeUserArea::DrawLine(): Draws a line.
- GeUserArea::DrawRectangle(): Draws a rectangle.
- GeUserArea::DrawFrame(): Draws a frame.
- GeUserArea::DrawBezierLine(): Draws a Bezier line.
- GeUserArea::DrawBezierFill(): Draws a Bezier line and fills the area.
- GeUserArea::DrawPolyLine(): Draws a poly line.
- GeUserArea::DrawPolyFill(): Draws a poly line and fills the area.
- GeUserArea::DrawEllipseLine(): Draws an ellipse.
- GeUserArea::DrawEllipseFill(): Draws an ellipse and fills the area.
{
DrawEllipseFill(center, radius);
DrawEllipseLine(center, radius);
}
{
DrawEllipseFill(center, radius);
}
{
DrawEllipseFill(center, radius);
}
{
}
unsigned char * p
Definition: floatobject.h:87
#define MAXON_SCOPE
Definition: apibase.h:2891
Block< T > ToSingletonBlock(T &value)
Definition: block.h:984
NORMAL
Definition: lib_birender.h:2
maxon::Vec2< maxon::Float64, 1 > Vector2d
Definition: ge_math.h:142
A BaseBitmap can both be drawn to the canvas and filled with the current pen:
- GeUserArea::DrawBitmap(): Draws a BaseBitmap. For effects see BMP.
- GeUserArea::FillBitmapBackground(): Fills the given BaseBitmap with the current pen color.
See also BaseBitmap Manual.
AutoAlloc<GeClipMap> clipMap;
if (clipMap)
{
BaseContainer font;
clipMap->Init(200, 50, 32);
clipMap->BeginDraw();
clipMap->SetColor(255, 255, 255, 255);
clipMap->FillRect(0, 0, 200, 50);
clipMap->SetFont(&font, 20.0);
clipMap->SetColor(0, 0, 0, 255);
clipMap->TextAt(0, clipMap->GetTextHeight(), "This is some text.");
clipMap->EndDraw();
BaseBitmap* const bitmap = clipMap->GetBitmap();
if (bitmap)
{
const Int32 height = bitmap->GetBh();
}
}
@ BMP_NORMAL
Standard scaling by the operating system. Fast but low quality when using uneven scaling factors.
Definition: gui.h:171
@ GE_FONT_DEFAULT_MONOSPACED
The Cinema 4D monospaced font.
Definition: lib_clipmap.h:121
unsigned long Py_ssize_t width
Definition: pycore_traceback.h:88
The border style of the user area is defined with:
- GeUserArea::DrawBorder(): Draws a border with the given style, see BORDER.
- GeUserArea::GetBorderSize(): Gets the space required to draw a border. Typically used with GeUserArea::GetMinSize().
@ BORDER_ROUND
Border with round corners.
Definition: gui.h:271
Text is drawn with these functions:
- GeUserArea::DrawText(): Draws the given String.
- GeUserArea::DrawSetTextCol(): Sets the text foreground and background color.
- GeUserArea::DrawSetFont(): Sets the text font, see FONT.
- GeUserArea::DrawGetTextWidth(): Returns the width in pixels of the given String.
- GeUserArea::DrawGetFontHeight(): Returns the height in pixels of the given String.
- GeUserArea::DrawGetTextWidth_ListNodeName(): Returns the width in pixels of the name of the given BaseList2D.
- GeUserArea::DrawGetFontBaseLine(): Returns the base line of the current font.
- GeUserArea::DrawSetTextRotation(): Sets the text rotation.
const String
text {
"Hello World!" };
const Int32 baseline = DrawGetFontBaseLine() + 1;
DrawLine(left, baseline, left +
length, baseline);
@ FONT_MONOSPACED
Monospaced font.
Definition: gui.h:25
PyWideStringList Py_ssize_t length
Definition: initconfig.h:448
PyObject * text
Definition: pycore_traceback.h:70
A user area can support a dynamic fading effect that is typically used to change the background color of the gadget after the cursor moved over it:
- GeUserArea::ActivateFading(): Activates the dynamic fading. The message ::BFM_FADE will be sent to the user area.
- GeUserArea::AdjustColor(): Calculates the new color while fading.
See also Fading.
class FadingUserArea : public GeUserArea
{
public:
FadingUserArea() { };
~FadingUserArea() { };
{
{
{
ActivateFading(100);
return true;
}
{
Redraw();
return true;
}
}
}
{
OffScreenOn();
SetClippingRegion(x1, y1, x2, y2);
DrawRectangle(x1, y1, x2, y2);
}
};
@ COLOR_BG_HIGHLIGHT
Definition: c4d_colors.h:329
@ COLOR_TRANS
Definition: c4d_colors.h:14
@ COLOR_CONSOLE_TEXT
Definition: c4d_colors.h:94
@ COLOR_BG
Definition: c4d_colors.h:16
@ BFM_FADE
Definition: gui.h:1009
It is also possible to be informed when the cursor leaves the user area:
- RemoveLastCursorInfo(): Registers a callback function that is called when the cursor leaves the user area. The function typically sends the message ::BFM_CURSORINFO_REMOVE back to the user area.
static void RemoveCursorInfo();
class RemoveCursorUserArea;
static RemoveCursorUserArea* g_userArea = nullptr;
class RemoveCursorUserArea : public GeUserArea
{
public:
RemoveCursorUserArea()
{
if (g_userArea == this)
g_userArea = nullptr;
};
~RemoveCursorUserArea() { };
{
{
{
g_userArea = this;
_cursorInside = true;
Redraw();
return true;
}
{
_cursorInside = false;
Redraw();
break;
}
}
}
{
OffScreenOn();
SetClippingRegion(x1, y1, x2, y2);
if (_cursorInside)
DrawSetPen(
Vector(1.0, 0.0, 0.0));
else
DrawSetPen(
Vector(0.0, 1.0, 0.0));
DrawRectangle(x1, y1, x2, y2);
}
private:
Bool _cursorInside =
false;
};
static void RemoveCursorInfo()
{
if (g_userArea == nullptr)
return;
BaseContainer bc;
}
@ BFM_CURSORINFO_REMOVE
Sent when mouse cursor has left a user area.
Definition: gui.h:577
Bool RemoveLastCursorInfo(LASTCURSORINFOFUNC func)
Clipping
Clipping is used to limit drawing operations to certain areas:
- GeUserArea::SetClippingRegion(): Specifies the clipping region for the drawing functions.
- GeUserArea::ClearClippingRegion(): Clears the clipping region set with GeUserArea::SetClippingRegion().
- GeUserArea::OffScreenOn(): Enables double buffering to avoid blinking and flickering effects. Automatically sets the clipping area to the whole user area or the given region.
{
OffScreenOn();
SetClippingRegion(x1, y1, x2, y2);
DrawRectangle(x1, y1, x2, y2);
}
Miscellaneous
Miscellaneous functions are:
- GeUserArea::ScrollArea(): Scrolls the user area.
- GeUserArea::GetPixelRatio(): Returns the screen pixel ratio to indicate Retina displays.
Coordinate Transformation
These functions are used to transform coordinates into different spaces:
- GeUserArea::Local2Global(): Transforms local coordinates to global window coordinates.
- GeUserArea::Global2Local(): Transforms global window coordinates to local coordinates.
- GeUserArea::Local2Screen(): Transforms local coordinates to screen coordinates.
- GeUserArea::Screen2Local(): Transforms screen coordinates to local coordinates.
Bool InputEvent(
const BaseContainer&
msg)
{
{
BaseContainer bc;
bc.InsData(5159, "CMD");
bc.InsData(0, String());
bc.InsData(5160, "CMD");
return true;
}
return false;
}
PyObject * x
Definition: bytesobject.h:38
@ BFM_INPUT_MOUSERIGHT
Right mouse button.
Definition: gui.h:717
Int32 ShowPopupMenu(CDialog *cd, Int32 screenx, Int32 screeny, const BaseContainer &bc, Int32 flags=POPUP_RIGHT|POPUP_EXECUTECOMMANDS|POPUP_ALLOW_FILTERING, Int32 *res_mainid=nullptr)
const Class< R > & Get(const Id &cls)
Definition: objectbase.h:2090
Further Reading