利用EasyX绘制按钮,实现按钮的鼠标悬浮、按下、d起效果。
效果展示 实现原理在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] = ''; 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; }
- 利用实现的简易框架实现的一个文本编辑器效果
链接:https://pan.baidu.com/s/1eT_kdtSWlY57GYRlXDroKg
提取码:1111
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)