Main Index : Reference :

GeUserArea


Description

A user area class that can be used to create custom GUI components.

Definition

class GeUserArea
{
public:
  GeUserArea([int] id, [GeBaseDialog] dialog);

  // Overload for easy message handling
  [bool] Init();
  [int] GetUserWidth();
  [int] GetUserHeight();
  [bool] Sized([int] width, [int] height);
  [bool] Draw([int] x1, [int] y1, [int] x2, [int] y2);
  [bool] InputEvent([BaseContainer] msg);
  [bool] CoreMessage([int] id, [BaseContainer] msg);
  [bool] Timer([BaseContainer] msg);

  // Overload for special message handling
  [int] Message([BaseContainer] msg);

  // Functions
  [bool] SendParentMessage([BaseContainer] msg);
  [bool] Redraw();
  [int] GetId();
  [int] GetWidth();
  [int] GetHeight();

  // Input events and timer
  [bool] SetTimer([int] timer);
  [bool] KillEvents();
  [BaseContainer] GetInputState([int] askdevice, [int] askchannel);
  [BaseContainer] GetInputEvent([int] askdevice);

  // Pens
  [bool] DrawSetPen([vector,int] color);
  [bool] DrawSetTextPen([vector,int] fg, [vector,int] bg);

  // Draw functions
  [bool] DrawLine([int] x1, [int] y1, [int] x2, [int] y2);
  [bool] DrawRectangle([int] x1, [int] y1, [int] x2, [int] y2);
  [bool] DrawBitmap([BaseBitmap] bmp, [int] bmp_x1, [int] bmp_y1, [int] bmp_x2, 
                    [int] bmp_y2, [int] area_x1, [int] area_y1, [int] area_x2, 
                    [int] area_y2,  [int] mode);
  [bool] DrawText([string] text, [int] x, [int] y);
  
  [bool] FillBitmapBackground([BaseBitmap] bmp, [int] xoffset, [int] yoffset);
    
  // Fonts
  [bool] DrawSetFont([int] fontid);
  [int] DrawGetTextWidth([string] text);
  [int] DrawGetFontHeight();

  // Others
  [bool] OffScreenOn();

  [bool] SetClippingRegion([int] x1, [int] y1, [int] x2, [int] y2);
  [bool] ClearClippingRegion();

  [bool] ScrollArea([int] dx, [int] dy, [int] x1, [int] y1, [int] x2, [int] y2);

  [int] Global2LocalX();
  [int] Global2LocalY();
}

Explanation

There are already dozens of predefined buttons in the GUI easy available. But if one wants to make one's own buttons or just wants to program an async manager window with a custom draw area, one needs to use user areas. Every user area has a specified drawing area and several commands for drawing lines or text. So you can do whatever you want, either program a 3D trackball or make a tree like object manager.

Members

GeUserArea( id, dialog )

GeUserArea([int] id, [GeBaseDialog] dialog);

Constructor. One must specify the id of the area and the dialog the area should be attached to. The user area id must be registered to the dialog first, either with AddUserArea() or using a dialog resource, before one allocates it:

// Register a user area with id 5000 first.
AddUserArea(5000,0,0,0);

// Then allocate and attach the user area.
ua = new(MyUserArea,5000,this);

Init()

[bool] Init();

Called when the user area is initialized by the GUI. One should overload this function if one wants to initialize any local variables before the first redraw. Return TRUE if successful.

GetUserWidth()

[int] GetUserWidth();

Should return the minimum width of the user area.

GetUserHeight()

[int] GetUserHeight();

Should return the minimum height of the user area.

Sized( width, height )

[bool] Sized([int] width, [int] height);

Whenever the user area has been resized, this function will be called to tell you the new size. (This is only possible with asynchronous dialogs.)

Draw( x1, y1, x2, y2 )

[bool] Draw([int] x1, [int] y1, [int] x2, [int] y2);

This function is called whenever the GUI wants the user area to be redrawed.

Note: One can speed up the redraw by using the area defined by (x1,y1) to (x2,y2). Especially when having overlapping windows one only needs to redraw this partial area. However, if you are not sure how to program this, just paint the whole area defined by (0,0) to (GetWidth-1,GetHeigth()-1).

InputEvent( msg )

[bool] InputEvent([BaseContainer] msg);

Overload this function to be able to react to input events. All information about the input event is stored in the msg container. The input device is accessed with:

var device = msg->GetData(BFM_INPUT_DEVICE);

Device Explanation
BFM_INPUT_MOUSE Mouse input
BFM_INPUT_KEYBOARD Keyboard input

If device is BFM_INPUT_KEYBOARD one can access the following container values in msg:

Container ID Type Explanation
BFM_INPUT_ASC [string] The input character as a string
BFM_INPUT_CHANNEL [int] The raw code of the key
BFM_INPUT_VALUE [float] A value between 0.0 and 1.0

If device is BFM_INPUT_MOUSE one can get the following values:

Container ID Type Explanation
BFM_INPUT_CHANNEL [int] What triggered the event:
  BFM_INPUT_MOUSELEFT   Left mouse button
  BFM_INPUT_MOUSERIGHT   Right mouse button
  BFM_INPUT_MOUSEMIDDLE   Middle mouse button
  BFM_INPUT_MOUSEWHEEL   Mouse wheel
BFM_INPUT_X [float] X value of the channel
BFM_INPUT_Y [float] Y value of the channel
BFM_INPUT_Z [float] Z value of the channel
BFM_INPUT_VALUE [float] For pressure sensitive devices,
and the mouse wheel channel
BFM_INPUT_DOUBLECLICK [bool] TRUE if doubleclicked

Currently there are no supported pressure sensitive devices, so BFM_INPUT_VALUE is either 0 or 1. When used by the mouse wheel channel it represents the positive or negative amount of scrolling (usually -120 or 120).

Please keep in mind that the mouse coordinates are given in global coordinates, so one might have to use Global2LocalX() and Global2LocalY() to transform them.

The state of keyboard qualifiers, for example the shift key, are accessed with:

var qualifier = msg->GetData(BFM_INPUT_QUALIFIER);

The following bits are used in the resulting integer value:

Qualifier Explanation
QSHIFT Shift key
QCTRL Ctrl key
QALT Alt key
QALT2
QALT3 Apple command key

As there is no operating system that can guarantee that a mouse up event is delivered, it is recommended to poll the mouse manually until it's released. This is done with GetInputState():

while(TRUE)
{
  // Poll the mouse device, left mouse button
  var state = GetInputState(BFM_INPUT_MOUSE, BFM_INPUT_MOUSELEFT);
  
  // Check if the mouse button is depressed
  if (state->GetData(BFM_INPUT_VALUE) == 0.0) break; 
  
  // Otherwise get the coordinates
  var gx = state->GetData(BFM_INPUT_X);
  var gy = state->GetData(BFM_INPUT_Y);

  // Transform them to local coordinates
  var x = Global2LocalX(gx);
  var y = Global2LocalY(gy);

  // Do whatever...
}

If one is designing a real element, for example a slider, one might also want to send regular messages to the parent dialog. These are sent with SendParentMessage() and appear as calls to Command() in the dialog, just as with any regular element:

// Create an action message, 
// with the user area's id:
var action = new(BaseContainer, BFM_ACTION);
action->SetData(BFM_ACTION_ID, GetId());

while(TRUE)
{
  // Poll the mouse as above and draw the slider.

  // Send a message to the parent dialog, so that
  // it knows that the user is dragging the slider:
  action->SetData(BFM_ACTION_INDRAG, TRUE);
  SendParentMessage(action);
}

// Notify the dialog that the dragging is finished:
action->SetData(BFM_ACTION_INDRAG, FALSE);
SendParentMessage(action);

CoreMessage( id, msg )

[bool] CoreMessage([int] id, [BaseContainer] msg);

Overload this function if you want to react to C4D core messages. For a list of possible message ids, please see GeDialog.

Timer( msg )

[bool] Timer([BaseContainer] msg);

If one subscribes to the timer event using SetTimer(x), this function is called every xth millisecond.


Message( msg )

[int] Message([BaseContainer] msg);

Overload this function if you want to react to more messages then covered by the above virtual functions. Normally this is not necessary.


SendParentMessage( msg )

[bool] SendParentMessage([BaseContainer] msg);

Use this function to send a custom message to the parent dialog. Returns TRUE if successful.

Redraw()

[bool] Redraw();

Force the user area to redraw itself by calling the Draw() function with the right region. Returns TRUE if successful.

GetId()

[int] GetId();

Returns the id of the user area.

GetWidth()

[int] GetWidth();

Returns the width of the user area.

GetHeight()

[int] GetHeight();

Returns the height of the user area.


SetTimer( timer )

[bool] SetTimer([int] timer);

Subscribes to the timer event message, making CINEMA 4D call Timer() every timer milliseconds.

Note: Depending on the speed of the computer, the operating system, the complexity of the dialog and the threads running in the background, there is no guarantuee that event messages will occur on a regular basis. Using a value of 500 ms should be no problem but if using a value of 1 ms one might get events with the following time spaces: 3 ms, 76 ms, 15 ms, 19 ms, 67 ms...

Remember: Keep in mind that using small timer values results in heavy message traffic in the application which may slow down CINEMA 4D (and all other applications running on the computer) to a point where nothing is working any longer besides your dialog.

KillEvents()

[bool] KillEvents();

Flushes all events from the window message queue. For example if you loop while the mouse is down (polling) you can call this command to flush all keydowns/mouseclicks that are made during the loop.

GetInputState( askdevice, askchannel )

[BaseContainer] GetInputState([int] askdevice, [int] askchannel);

Polls a certain channel of a device for the current input state. The returned container is just like an input event message. For a list of valid devices and channels, please see InputEvent().

GetInputEvent( askdevice )

[BaseContainer] GetInputEvent([int] askdevice);

Gets the next input event for a certain device from the event queue. The returned container is just like an input event message. For a list of valid devices, please see InputEvent().


DrawSetPen( color )

[bool] DrawSetPen([vector,int] color);

Sets the draw color, either by using a color vector or one of the following predefined palette colors:

Palette color Explanation
COLOR_BG Background (normally gray but might
as well be a user pattern)
COLOR_BGEDIT Edit fields background
COLOR_BGFOCUS Focus background
COLOR_TEXT Text color
COLOR_TEXTFOCUS Focus text color
COLOR_EDGELT Light edge
COLOR_EDGEWH Lightest edge
COLOR_EDGEDK Dark edge
COLOR_EDGEBL Darkest edge
COLOR_DBARFG1 Inactive text dialogbar
COLOR_DBARBG1 Inactive background dialogbar
COLOR_DBARFG2 Active text dialogbar
COLOR_DBARBG2 Active background dialogbar
COLOR_BGGADGET Gadget background

DrawSetTextPen( fg, bg )

[bool] DrawSetTextPen([vector,int] fg, [vector,int] bg);

Sets the text foreground and background color, either by using color vectors or one of the predefined palette colors (see DrawSetPen()). As background color one can also use COLOR_TRANS, which gives a transparent text background.


DrawLine( x1, y1, x2, y2 )

[bool] DrawLine([int] x1, [int] y1, [int] x2, [int] y2);

Draws a line from the point (x1,y1) to the point (x2,y2) using the current pen color. Returns TRUE if successful.

DrawRectangle( x1, y1, x2, y2 )

[bool] DrawRectangle([int] x1, [int] y1, [int] x2, [int] y2);

Fills a rectangle area with the upper left corner at the point (x1,y1) and the lower right corner at the point (x2,y2) using the current pen color. Returns TRUE if successful.

DrawBitmap( bmp, bmp_x1, bmp_y1, bmp_x2, bmp_y2, area_x1, area_y1, area_x2, area_y2, mode )

[bool] DrawBitmap([BaseBitmap] bmp, [int] bmp_x1, [int] bmp_y1, [int] bmp_x2, 
                  [int] bmp_y2, [int] area_x1, [int] area_y1, [int] area_x2, 
                  [int] area_y2,  [int] mode);

Draws a bitmap into the user area. The region (bmp_x1,bmp_y1) to (bmp_x2,bmp_y2) from the bitmap will be scaled and transformed into the region (area_x1,area_y1) to (area_x2,area_y2) of the destination area. The following options are available for the mode parameter:

Option Explanation
BMP_NORMAL Standard scaling by the operating system. Fast but
low quality when using uneven scaling factors.
BMP_NORMALSCALED Scaling with sampling for high quality. Slow.
BMP_DARKEN Darkens the bitmap (like the activated
palette icons in CINEMA 4D).
BMP_EMBOSSED Embosses the bitmap (like the grayed
palette icons in CINEMA 4D).

DrawText( text, x, y )

[bool] DrawText([string] text, [int] x, [int] y);

Draws the string text at the position (x,y).


FillBitmapBackground( bmp, xoffset, yoffset )

[bool] FillBitmapBackground([BaseBitmap] bmp, [int] xoffset, [int] yoffset);

Fills the bitmap bmp with the current pen color. The xoffset and yoffset parameters are used when the current color is a pattern and are given in local coordinates of the user area. This can be used to for example make semi-transparent bitmap blits. Returns TRUE if successful. The following is an example of how the command is used:

SetPen(COLOR_BG);
FillBitmapBackground(bmp, 0, 0);

DrawSetFont( fontid )

[bool] DrawSetFont([int] fontid);

Sets the text font to fontid. Returns TRUE if successful. The following font ids can be used:

Font id Explanation
FONT_DEFAULT Default text font
FONT_STANDARD Standard text font
FONT_BOLD Bold font
FONT_MONOSPACED Monospaced font

DrawGetTextWidth( text )

[int] DrawGetTextWidth([string] text);

Returns the width of the string text in pixels using the current font.

DrawGetFontHeight()

[int] DrawGetFontHeight();

Returns the height in pixels of a line of the current font.


OffScreenOn()

[bool] OffScreenOn();

Enables double buffering to avoid blinking and flickering effects. The GUI will automatically switch planes. Just call this function before drawing things.

Note: Depending on the size of the user area the time needed by GUI to transfer the buffers might be noticeble and slow down the redraw. It's not a big deal with let's say 100x100 pixels but using an area of 600x400 pixels on an older Mac might result in redraw times over 300 ms even without doing anything!


SetClippingRegion( x1, y1, x2, y2 )

[bool] SetClippingRegion([int] x1, [int] y1, [int] x2, [int] y2);

Should be used at the top of the Draw() function to specify the clipping region. Without specifying a dedicated clipping region everything will be painted, even if itīs outside the user area!

// By initializing the clipping area to the partial redraw area, 
// any funny effects outside the user area are prevented:

Draw(x1,y1,x2,y2)
{
  SetClippingRegion(x1,y1,x2,y2);
  DrawText("Very long text for output Test...",20,20);
}

ClearClippingRegion()

[bool] ClearClippingRegion();

Switches off the clipping.


ScrollArea( dx, dy, x1, y1, x2, y2 )

[bool] ScrollArea([int] dx, [int] dy, [int] x1, [int] y1, [int] x2, [int] y2);

Scrolls the area from (x1,y1) to (x2,y2) in the direction specified by dx and dy.


Global2LocalX()

[int] Global2LocalX();

Transforms the x part of global dialog coordinates (e.g. mouse coordinates) to local user area coordinates.

Global2LocalY()

[int] Global2LocalY();

Transforms the y part of global dialog coordinates (e.g. mouse coordinates) to local user area coordinates.