Fox-Toolkit: Introduct

xiaoxiao2021-03-06  24

---- Topic Title with logo --->

Fox-Toolkit: Introduction [Remove Frame]

In order to explain the tools you can use to build a Fox application, we will show some simple FOX applications. The first is a simple picture board. The running screen of this program is shown below:

Drawboard

Figure 1. Picture board program (picture http://www.fox-toolkit.org/introduct.html :-)

The discipline show us how to use the Fox layout manager, how to create a button, and how to process messages. It's enough to say enough, let's get started! The most beginning to do is the header file containing FOX. This is very simple, because only one file needs to include:

#include "fx.h"

Then we need a top window class derived from the FXmainWindow class. There should be only one main window; if you need other top windows, you are best derived from the FXDialogbox class or FxtopWindow class.

In this program, we generate a class called Scribble:

// Event Handler ObjectClass ScribbleWindow: Public FXMainWindow {// Macro for Class Hierarchy Declarations FXDeclare (ScribbleWindow)

The first line is that ScribbleWindow is derived from fxmainWindow; the FXmainWindow class is like most Fox classes, which is derived from the FXObject class. You will be able to derive it directly or indirectly from a simple parent class FXOBJECT in the Fox program to write.

FXDeclare (ScribbleWindow) macro defines a lot of member functions that are derived from the FxObject class; we use the macro because they are always unchanged, and the writing procedures will be more comfortable.

We added some member variables to save the window controls to be used, as well as the color of the brush; we also defined a sign that the mouse is pressed, and a discounted panel is dirty, that is, have been drawn symbols of:

private: FXHorizontalFrame * contents; // Content frame FXVerticalFrame * buttonFrame; // Button frame FXVerticalFrame * canvasFrame; // Canvas frame FXCanvas * canvas; // Canvas to draw into int mdflag; // Mouse button down int dirty; //? Canvas Has Been Painted? FxColor Drawcolor; // Color for the line

In order to meet the needs of the macro, we have to provide a default constructor:

protected: scribbleWindow () {}

Fox handles messages through a system that sends a user message to the corresponding object; in this program, the recipient of the message is a scribbleWindow class; therefore, we need to add an appropriate member function to accept the message and make the corresponding action; in Fox All message processing functions have the same argument list:

Long OnsomeCommand (FxObject * Sender, FXSelector SEL, VOID * PTR);

Where: Sender is the object that sent us a message. SEL is a selector, which is a combination of message types and marked, with actions you want to do with. PTR is a pointer to event-related data; usually, it points to a FXEVENT structure that includes an event that initiates a message.

For Scribble applications, we need to handle mouse messages and messages from two buttons:

public: long onPaint (FXObject *, FXSelector, void *); long onMouseDown (FXObject *, FXSelector, void *); long onMouseUp (FXObject *, FXSelector, void *); long onMouseMove (FXObject *, FXSelector, void *); Long oncmdclear (fxObject *, fxselector, void *); long onupdclear (fxObject *, fxselector, void *);

At the same time, ScribbleWindow needs to define some new message IDs; a message consists of a type and an ID mark; type definition what happens; ID indicates the source of the message; even if we know which object comes from, in many cases, There may be the same message from different objects, so it is still useful to use ID. then:

Public: enum {id_canvas = fxmainWindow :: id_last, id_clear, id_last};

Typically, we define a message identity list with an ENUM structure; because the ScribbleWindow class is derived from FXMainWindow, it naturally also receives all the messages that the FXMainWindow parent class can receive. Our new news should have different values; with them, we can define an additional ID_last label to let the compiler do this for us; a subclass of message queues can be from its parent class ID_LAST Beginning; even if new messages are added to the parent class, our messages can also be automatically re-numbered by the compiler.

The ScribbleApp class also needs to be defined as a constructor and a member function crete ():

Public: scribblewindow (fxapp * a); virtual void create ();

In our implementation, the GUI interface is actually created by the ScribbleWindow constructor. Function create () is a virtual function called by the system. Most of the FOX controls have this function. The creative process of the FOX control is divided into two steps: First, the client control is created by the normal C constructor; then, when the entire control tree is constructed, a simple call to the application's function crete () will create the entire control window. Although it takes two steps, usually the second step is to simply connect the constructed control with the displayed graphics.

Now, we are ready to implement this new class. Typically, the previous code is to be placed in a separate header file, and the implementation code is naturally put in a C source code file. Because this example is very simple, we also simply put all things in a file.

The first thing is to define a list of messages. The message list is just an array that associates the message type and the message identification with the member function of the class. With a message list, we can send the message to any object derived from fxObject. such:

FXDEFMAP (ScribbleWindow) ScribbleWindowMap [] = {// ________ Message_Type_____________________ID_______________Message_Handler_______ FXMAPFUNC (SEL_PAINT, ScribbleWindow :: ID_CANVAS, ScribbleWindow :: onPaint), FXMAPFUNC (SEL_LEFTBUTTONPRESS, ScribbleWindow :: ID_CANVAS, ScribbleWindow :: onMouseDown), FXMAPFUNC (SEL_LEFTBUTTONRELEASE, ScribbleWindow :: ID_CANVAS , ScribbleWindow :: onMouseUp), FXMAPFUNC (SEL_MOTION, ScribbleWindow :: ID_CANVAS, ScribbleWindow :: onMouseMove), FXMAPFUNC (SEL_COMMAND, ScribbleWindow :: ID_CLEAR, ScribbleWindow :: onCmdClear), FXMAPFUNC (SEL_UPDATE, ScribbleWindow :: ID_CLEAR, ScribbleWindow :: onUpdClear ),}; Please note this list: First, there are several messages with the same ID, but there are different types. The message type indicates what happens, for example, SEL_LEFTBUTTONPRESS indicates that the left button just pressed. The message ID indicates the source of the message. Fox defines a lot of message types with special meanings.

Then we need to implement the "template" function defined by the FXDeclare macro:

FXIMPLEMENT (ScribbleWindow, FxmainWindow, ScribbleWindowMap, ArrayNumber (ScribbleWindowMap)

Among them, the first parameter of the macro should be our class name, namely ScribbleWindow; the second parameter should be our parent class name, here for fxmainwindow; the next two parameters are pointers that point to the message list and list elements Number. Fox has a very easy to use macro ArrayNumber () to help us calculate the length of the array in compile period, which makes us more convenient when adding a message.

If your class does not define other messages, the last two parameters can be simply set to NULL and 0.

The remaining implementation of ScribbleWindow is the standard C code. The constructor is as follows:

// Construct a ScribbleWindowScribbleWindow :: ScribbleWindow (FXApp * a): FXMainWindow (a, "ScribbleApplication", NULL, NULL, DECOR_ALL, 0,0,800,600) {contents = new FXHorizontalFrame (this, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0,0, 0, 0, 0, 0, 0); // Left Pane to Contain The Canvas Canvasframe = New FXVerticalFrame (Contents, Frame_Sunken | Layout_Fill_x | Layout_Fill_y | Layout_top | Layout_Left, 0, 0, 0, 10, 10, 10, 10,10); // Label above the canvas new FXLabel (canvasFrame, "canvasFrame", NULL, JUSTIFY_CENTER_X | LAYOUT_FILL_X); // Horizontal divider line new FXHorizontalSeparator (canvasFrame, SEPARATOR_GROOVE | LAYOUT_FILL_X); // Drawing canvas canvas = new FXCanvas (canvasFrame, this, ID_CANVAS, FRAME_SUNKEN | FRAME_THICK | LAYOUT_FILL_X | LAYOUT_FILL_Y | LAYOUT_TOP | LAYOUT_LEFT); // RIGHT pane for the buttons buttonFrame = new FXVerticalFrame (contents, FRAME_SUNKEN | LAYOUT_FILL_Y | LAYOUT_TOP | LAYOUT_LEFT, 0,0,0,0, 10, 10, 10, 10); // Label Above The Button s new FXLabel (buttonFrame, "ButtonFrame", NULL, JUSTIFY_CENTER_X | LAYOUT_FILL_X); // Horizontal divider line new FXHorizontalSeparator (buttonFrame, SEPARATOR_RIDGE | LAYOUT_FILL_X); // Button to clear new FXButton (buttonFrame, "& Clear", NULL, this, ID_CLEAR, FRAME_THICK | FRAME_RAISED | LAYOUT_FILL_X | LAYOUT_TOP | LAYOUT_LEFT, 0, 5, 0, 0, 10, 10, 5, 5); // Exit Button New FXButton (ButtonFrame, "& Exit", null, getapp (), FXAPP: : Id_quit, frame_thick | frame_raiad | layout_fill_x | layout_top | layout_left, 0,0,0,0,10,10,5,5); // Initialize Private variables DrawColor = FXRGB (255, 0, 0); mdflag = 0; Dirty = 0;}

In most cases, a FOX control of the build army requires only a line of C code, that is, the constructor. Moreover, because most of the FOX controls provide a lot of default parameters, we don't have to specify them. The first line created a top window. The top window in the FOX does not have a parent class, so you have to pass a pointer for an Application object to it (this is this). The rest of the parameters are window titles, custom types (such as size adjustments, borders, etc.), as well as initial size and location. The initial size and location may be ignored by the window manager, which only make it a reference.

The next line creates a FxhorzontalFrame control. The FxhorzontalFrame control is a layout manager that is arranged laterally.

The FXMainWindow control is also a layout manager, and the Option parameter passed to the FxhorzontalFrame control constructor will determine its place in fxmainwindow.

Then, the two FxVerticalFrame controls are created, one of which is used to place the discipline, and the other puts the button. Next, we put a label, a horizontal separator, and a drawing board in Canvasframe. Canvas's target object is set to scribbleapp (that is, its message identification is set to ID_canvas, so that CANVAS sends its messages to the ScribbleWindow object, its ID is ID_canvas.

Similarly, we put a label, a horizontal separator, and two buttons on the backtonframe on the right. The title of the clear screen button is "& clear". The & symbol will automatically create a shortcut ALT-C for the button. The letter C in the title is plus a next line, ie "clear". The target object of the clear screen button is also ScribbleApp, and its message is identified as id_clear. At the same time, the logo of the exit button is id_quit.

It should be noted that we do not need to define id_quit because FxApp has been defined. Therefore, we simply simply associate our buttons.

The remaining parameters determine the styles of the button (frame_thick | frame_raised), and how it will be placed on the VerticalFrame layout manager (layout_fill_x | layout_top | layout_left), the parameters of this example will make the button to elongate within a certain range Has the same length to appear neat.

Finally, the ScripbleWindow constructor initializes the value of its member variable to set the color and flag of the brush.

Next, let's implement the create () function:

// Create and Initializevoid ScribbleWindow :: Create () {// Create The Windows FXmainWindow :: Create (); // make the main window Appear show ();

First, we call the CREATE method of the parent class; then, by calling the show () function, the main window is displayed.

Next, we have to handle the message:

// Mouse button was pressed somewherelong ScribbleWindow :: onMouseDown (FXObject *, FXSelector, void *) {// While the mouse is down, we'll draw lines mdflag = 1; return 1;} // The mouse has moved, draw a linelong ScribbleWindow :: onMouseMove (FXObject *, FXSelector, void * ptr) {FXEvent * ev = (FXEvent *) ptr; if (mdflag) {// Get DC for the canvas FXDCWindow dc (canvas); // Set foreground color Dc.setForeground (DrawColor); // Draw Line DC.Drawline (EV-> Last_x, EV-> Last_Y, EV-> WIN_X, EV-> Win_Y); // We Have Drawn Something, Sonow The Canvas Is Dirty Dirty = 1;} return 1;} // The mouse button was released againlong ScribbleWindow :: onMouseUp (FXObject *, FXSelector, void * ptr) {FXEvent * ev = (FXEvent *) ptr; if (mdflag) {FXDCWindow dc (canvas) DC.SetForeground (DrawColor); dc.drawline (EV-> Last_x, EV-> Last_Y, EV-> WIN_X, EV-> Win_Y); // We Have Drawn Something, Sonow The Canvas Is Dirty = 1; / / Mouse no longer down mdflag = 0;} Return 1;} // Paint the canvaslong scribbleWindow :: onpaint (fxObject *, fxselector, void * PTR) {FXEVENT * EV = (FXEvent *) PTR; FXDCWindow DC (canvas, ev); dc.setForeground (canvas-> getBackcolor ()); DC.FillRectangle (EV-> Rect.x, EV-> RECT. Y, EV-> Rect.w, EV-> Rect.h); return 1;} The ONMOUSEDOWN message processing function simply sets the mark pressed by the mouse. The ONMOUSEMOVE message handler is drawn from the current position to the current location, and then the DIRTY variable is set to indicate that the discipline has been drawn. The ONMOUSEUP message handler ends the line and resets the flag. Finally, the ONPAINT message processing function fills the drawing board in the background color. This is nothing special.

Some of the message processing functions below is more interesting:

// Handle the clear messagelong ScribbleWindow :: onCmdClear (FXObject *, FXSelector, void *) {FXDCWindow dc (canvas); dc.setForeground (canvas-> getBackColor ()); dc.fillRectangle (0,0, canvas-> getWidth (), canvas-> getHeight ()); dirty = 0; return 1;} // update the clear buttonlong scribbleWindow :: onupdclear (fxObject * sender, fxselector, void *) {if (dirty) Sender-> handle (this , FXSEL (SEL_COMMAND, ID_ENABLE), NULL, ELSE Sender-> Handle (this, fxsel (sel_command, id_disable), null; return 1;} OncMdclear message processing function empty picture board, then reset DIRTY reset. OnUpdClear message handler Update the Clear button.

In Fox, each control receives a message called it update when the message loop is free. For example, when the application is changed, the button will be activated or expired; in this example, when the discipline is emptied, we will make the Clear button to fail; and when it is drawn (this is marked by Dirty flag) We will reactivate it.

This GUI update process is very effective: - If our application has N commands, and each command will update M control, we may need to write NXM update routines; to use the GUI update processing If we only need to write N M mechanical routines. In addition, if the data of the application is changed by other factors (such as clock control, external data input, and multi-thread operation, the GUI automatically updates its own state without requiring additional code.

In order to complete our Scribble program, there is only one thing to do: That is to start it in the main () function.

// Here We Beginint Main (Int Argc, Char * Argv []) {// make application fxapp * application = new fxapp ("scribble", "test"); // start app Application-> init (argc, argv) ; // scribble window new scribbleWindow (Application); // Create The Application's Windows Application-> Create (); // Run the Application Application-> Run (); Return 0;}

First, we created a FXAPP object through new fxapp ("scribble", "test"). The first string "scribble" is the program name, which is generally used as a keyword for the program; at the same time, the second string "Test" is the seller keyword. These two keywords are used to determine the registration information of the program.

The next function calls Application-> Init (argc, argv) to initialize the application. The two parameters of Argc and Argv are incorporated to enable the Fox system to handle some command line parameters unique to Fox, such as -display, etc.

Next statement new scribbleWindow creates a whole GUI for our app. It is actually composed of two parts: one is client resource, under our control; the other is server resources, namely X Server (X11) or GDI (Windows). When we create a FOX control, it is actually just that the client resource is created. A recursive call to a function Application-> Create () creates server resources for all controls. Finally, the call to the Application-> Run () member function makes the entire application until we exit.

转载请注明原文地址:https://www.9cbs.com/read-40358.html

New Post(0)