EasyX实现按钮效果

这篇博客介绍了如何使用EasyX图形库创建按钮并实现鼠标悬浮、按下、弹起效果。通过封装窗口控件和消息派发机制,作者展示了如何在C语言中创建窗体元素,如按钮和文本框,并处理键盘和鼠标事件。此外,还提供了一个简单的文本编辑器应用作为示例,展示了该框架的实际应用。
摘要由CSDN通过智能技术生成

EasyX实现按钮效果

利用EasyX绘制按钮,实现按钮的鼠标悬浮、按下、弹起效果。

效果展示

按钮效果.gif

实现原理

在EasyX现有基础上,实现了widget窗口元素,并用C语言的方式,从widget派生出button(按钮)、label(文本框)等窗口控件,利用container窗口容器进行管理,并封装了鼠标和键盘按键,实现了简易的消息派发机制,使得程序逻辑只需关心按钮被按下的消息事件,而无需做鼠标坐标和图形区域判断。

  • 消息机制的封装(部分代码)
/*********************
* 框架 - 消息派发
**********************/

#define TASK_QUEUE_SIZE 10

typedef struct _tTaskInfo {
    int type;
    void* data;
} TaskInfo;

typedef struct _tTaskQueue {
    TaskInfo* data;
    int front;
    int rear;
    int capacity;
} TaskQueue;

//创建事件
typedef void* (*CallCreate)();
//销毁事件
typedef void (*CallDestroy)(void* context);
//键盘事件
typedef int (*CallKeyBoard)(int key, TaskQueue* queue, void* context);
//鼠标事件
typedef int (*CallMouse)(MOUSEMSG* msg, TaskQueue* queue, void* context);
//任务事件
typedef int (*CallTask)(TaskQueue* queue, void* context);
//空闲事件
typedef int (*CallIdle)(void* context);

//运行环境
typedef struct _tRuntime {
    void* context;
    CallCreate create;
    CallDestroy destroy;
    CallKeyBoard keyboard;
    CallMouse mouse;
    CallTask task;
    CallIdle idle;
} Runtime;

TaskQueue* createTaskQueue(int capacity) {
    TaskQueue* queue = (TaskQueue*)malloc(sizeof(TaskQueue));
    memset(queue, 0, sizeof(TaskQueue));
    queue->capacity = capacity;
    queue->data = (TaskInfo*)malloc(sizeof(queue->data[0]) * capacity);
    memset(queue->data, 0, sizeof(sizeof(queue->data[0]) * capacity));
    return queue;
}

void destroyTaskQueue(TaskQueue* queue) {
    if (queue) {
        free(queue->data);
        free(queue);
    }
}

int emptyTaskQueue(TaskQueue* queue) {
    return (queue && queue->front == queue->rear);
}

int fullTaskQueue(TaskQueue* queue) {
    return (queue && queue->front == ((queue->rear + 1) % queue->capacity));
}

void enqueueTaskQueue(TaskQueue* queue, int type, void* data) {
    if (queue) {
        if (!fullTaskQueue(queue)) {
            int pos = queue->rear;
            TaskInfo* task = &queue->data[pos];
            queue->rear = (pos + 1) % queue->capacity;
            task->type = type;
            task->data = data;
        }
    }
}

void dequeueTaskQueue(TaskQueue* queue, TaskInfo* task) {
    if (queue) {
        if (!emptyTaskQueue(queue)) {
            int pos = queue->front;
            queue->front = (pos + 1) % queue->capacity;
            *task = queue->data[pos];
        }
    }
}

Runtime createRuntime(CallCreate create, CallDestroy destroy, CallKeyBoard keyboard, CallMouse mouse, CallTask task, CallIdle idle) {
    Runtime runtime = { NULL, create, destroy, keyboard, mouse, task, idle };
    return runtime;
}

int dispatchMessage(Runtime* runtime) {
    void* context = runtime->create();
    TaskQueue* queue = createTaskQueue(TASK_QUEUE_SIZE);
    int ret = 0;
    FlushMouseMsgBuffer();
    while (1) {
        if (runtime->keyboard && _kbhit()) {
            int key = _getch();
            ret = runtime->keyboard(key, queue, context);
            if (ret != 0) {
                break;
            }
        } else if (runtime->mouse && MouseHit()) {
            MOUSEMSG msg = GetMouseMsg();
            ret = runtime->mouse(&msg, queue, context);
            if (ret != 0) {
                break;
            }
        } else if (runtime->task && !emptyTaskQueue(queue)) {
            ret = runtime->task(queue, context);
            if (ret != 0) {
                break;
            }
        } else if (runtime->idle) {
            ret = runtime->idle(context);
            if (ret != 0) {
                break;
            }
        }
    }
    destroyTaskQueue(queue);
    runtime->destroy(context);
    return ret;
}
  • 窗体控件的封装(部分代码)
/*********************
* 框架 - 窗体控件
**********************/

#define STYLE_BK_COLOR 0xFFFFFF
#define STYLE_WIDGET_BUTTON_COLOR_LINE 0x808080
#define STYLE_WIDGET_BUTTON_COLOR_FILL 0x808080
#define STYLE_WIDGET_BUTTON_COLOR_TEXT 0xFFFFFF
#define STYLE_WIDGET_BUTTON_COLOR_FOCUS 0x404040
#define STYLE_WIDGET_BUTTON_SHADOW_COLOR 0xC0C0C0
#define STYLE_WIDGET_BUTTON_SHADOW_OFFSET_X 3
#define STYLE_WIDGET_BUTTON_SHADOW_OFFSET_Y 3
#define STYLE_WIDGET_BUTTON_FONT_HEIGHT 16

enum {
    WIDGET_TYPE_NULL,
    WIDGET_TYPE_CONTAINER,
    WIDGET_TYPE_BUTTON,
    WIDGET_TYPE_LABEL,
};

enum {
    WIDGET_LABEL_ALIGN_LEFT,
    WIDGET_LABEL_ALIGN_CENTER,
};

enum {
    WIDGET_FLAG_NULL = 0,
    WIDGET_FLAG_FOCUS = 1 << 0,
    WIDGET_FLAG_CLICK = 1 << 1
};

typedef struct _tPoint {
    int x;
    int y;
} Point;

typedef struct _tRect {
    Point point;
    int width;
    int height;
} Rect;

typedef struct _tWidget {
    int type;
    int id;
    int flag;
    Rect rect;
} Widget;

typedef struct _tWidgetList {
    Widget** data;
    int size;
    int capacity;
} WidgetList;

typedef struct _tWidgetContainer {
    Widget widget;
    WidgetList* list;
} WidgetContainer;

typedef struct _tWidgetButton {
    Widget widget;
    wchar_t* text;
} WidgetButton;

typedef struct _tWidgetLabel {
    Widget widget;
    int font_height;
    int align;
    COLORREF fill_color;
    COLORREF line_color;
    COLORREF text_color;
    COLORREF focus_color;
    wchar_t* text;
} WidgetLabel;

wchar_t* convertCharToWchar(const char* input);
WidgetList* createWidgetList(int capacity);
void destroyWidgetList(WidgetList* list);
void appendWidgetList(WidgetList* list, Widget* widget);
WidgetContainer* createWidgetContainer(int id, int x, int y, int width, int height);
void appendWidgetContainer(WidgetContainer* container, Widget* widget);
void destroyWidgetContainer(WidgetContainer* container);
WidgetButton* createWidgetButton(int id, int x, int y, int width, int height, const char* text);
void destroyWidgetButton(WidgetButton* button);
void drawWidgetButton(WidgetButton* button);
WidgetLabel* createWidgetLabel(int id, int x, int y, int width, int height, int font_height, COLORREF fill_color, COLORREF line_color, COLORREF text_color, COLORREF focus_color, int align, const char* text);
void destroyWidgetLabel(WidgetLabel* label);
void drawWidgetLabel(WidgetLabel* label);
void drawWidgetContainer(WidgetContainer* container);
int hitWidget(Widget* widget, MOUSEMSG* msg);
Widget* hitWidgetContainer(WidgetContainer* container, MOUSEMSG* msg);

wchar_t* convertCharToWchar(const char* input) {
    int input_len = (int)strlen(input);
    int output_len = MultiByteToWideChar(CP_ACP, 0, input, input_len, NULL, 0);
    wchar_t* output = new wchar_t[output_len + 1];
    MultiByteToWideChar(CP_ACP, 0, input, input_len, output, output_len);
    output[output_len] = '\0';
    return output;
}

char* convertWcharToChar(const wchar_t* input) {
    int nLen = WideCharToMultiByte(CP_ACP, 0, input, -1, NULL, 0, NULL, NULL);
    if (nLen == 0) {
        return NULL;
    }
    char* output = new char[nLen];
    WideCharToMultiByte(CP_ACP, 0, input, -1, output, nLen, NULL, NULL);
    return output;
}

char* inputEditBox(const char* title, const char* prompt, const char* defaul, int width, int height) {
    wchar_t buffer[1024] = { 0 };
    wchar_t* _title = title ? convertCharToWchar(title) : NULL;
    wchar_t* _prompt = prompt ? convertCharToWchar(prompt) : NULL;
    wchar_t* _defaul = defaul ? convertCharToWchar(defaul) : NULL;
    if (InputBox(buffer, sizeof(buffer) / sizeof(buffer[0]), _prompt, _title, _defaul, width, height)) {
        return convertWcharToChar(buffer);
    }
    return NULL;
}

WidgetList* createWidgetList(int capacity) {
    WidgetList* list = (WidgetList*)malloc(sizeof(WidgetList));
    memset(list, 0, sizeof(WidgetList));
    list->capacity = capacity;
    list->data = (Widget**)malloc(sizeof(Widget*) * list->capacity);
    memset(list->data, 0, sizeof(Widget*) * list->capacity);
    return list;
}

void destroyWidgetList(WidgetList* list) {
    if (list) {
        for (int index = 0; index < list->size; ++index) {
            Widget* widget = list->data[index];
            switch (widget->type) {
            case WIDGET_TYPE_CONTAINER:
                destroyWidgetContainer((WidgetContainer*)widget);
                break;
            case WIDGET_TYPE_BUTTON:
                destroyWidgetButton((WidgetButton*)widget);
                break;
            case WIDGET_TYPE_LABEL:
                destroyWidgetLabel((WidgetLabel*)widget);
                break;
            }
        }
        free(list);
    }
}
  • 功能实现(部分)
int main() {
    Runtime runtime = createRuntime((CallCreate)callEditorCreate, \
        (CallDestroy)callEditorDestroy, \
        (CallKeyBoard)callEditorKeyBoard, \
        (CallMouse)callEditorMouse, \
        (CallTask)callEditorTask, \
        (CallIdle)callEditorIdle);

    dispatchMessage(&runtime);
    return 0;
}
  • 利用实现的简易框架实现的一个文本编辑器效果

文本编辑器.png

源码下载

链接:程序源码下载链接
提取码:1111

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值