中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

網(wǎng)站域名個人備案查詢推廣平臺排行榜app

網(wǎng)站域名個人備案查詢,推廣平臺排行榜app,一級注冊消防工程師報考條件,百度seo優(yōu)化價格目錄 面對對象C的程序設計(范例) 面對對象C的程序設計(應用) 進一步談論我上面給出的代碼——繼承 實現(xiàn)一個面對對象的文本編輯器 所以,什么是繼承 重申我們對菜單的抽象 抽象菜單項目 抽象菜單動畫 實現(xiàn)菜單功…

目錄

面對對象C的程序設計(范例)

面對對象C的程序設計(應用)

進一步談論我上面給出的代碼——繼承

實現(xiàn)一個面對對象的文本編輯器

所以,什么是繼承

重申我們對菜單的抽象

抽象菜單項目

抽象菜單動畫

實現(xiàn)菜單功能

初始化我們的菜單

關于我們的圖標設置,顯示和隱藏

菜單本體功能

關于切換focus的菜單和進入父子菜單的函數(shù)

完整的測試文件


終于,我們來到了這個令人激動的部分了,現(xiàn)在,我們終于把所有的基礎工作做好了,就差我們的動態(tài)組件了。

面對對象C的程序設計(范例)

我想,你可能使用過C++這門語言,他派生于C,但是最終的慣用編程范式又遠遠不同于C。盡管如此,C仍然可以按照一個相對變扭的方式完成面對對象的程序設計。這是因為在C語言本質(zhì)上是過程化語言,沒有直接的類和對象概念,因此面向?qū)ο笤O計需要通過結構體、函數(shù)指針等手段模擬實現(xiàn)。

面對對象,首先講究的就是把所有的目標看成對象。舉個例子,現(xiàn)在我們來看看動態(tài)多級菜單這個東西,按照面對對象的設計思路。我們說面對對象它通過抽象和封裝將數(shù)據(jù)與功能結合,形成具有特定屬性和行為的對象。

typedef struct {int x;int y;void (*move)(struct Point*, int, int);
} Point;
?
void movePoint(Point* p, int dx, int dy) {p->x += dx;p->y += dy;
}
?
int main() {Point p = {0, 0, movePoint};p.move(&p, 5, 3);return 0;
}

這個就是一個將點看作對象的例子。

我們設計對象的時候,要思考對象能干什么,進一步的,才需要知道他需要有什么。這種方式可以輔助一個習慣于面對過程的朋友設計一個對象。

面對對象C的程序設計(應用)

我們現(xiàn)在把上面談到的用一下。

  • 他能顯示多級的文字菜單

  • 他能將目前選中的文本區(qū)域進行反色

  • 他能再切換選中文本的時候演示一個阻塞的動畫(提示,筆者的框架沒有做異步,這需要牽扯到中斷,筆者不打算現(xiàn)在做)

  • 如果一個子項存在子菜單,他能顯示出來這個子菜單,然后還能返回去(怎么樣觸發(fā)進入和返回不是我們關心的,他能!

  • 他可以顯示和隱藏我們的icon,為此,我們還需要注冊接口。

為了做到上面的事情,我們要想他要擁有什么。

  • 一個簡略的文本編輯器,他能展示文字,我們菜單的文本繪制基本上依賴于這個文本編輯器

  • 一個負責動畫演示的結構體(對象),他能完成我們對“他能再切換選中文本的時候演示一個阻塞的動畫”這個任務

  • 一個菜單子項結構體數(shù)組,他維護了當前這個菜單子項的文本顯示,是否有子菜單,甚至,還需要有callback行為的結構體數(shù)組(這個是額外任務,筆者沒有做callback)

typedef void* CCgraphicWidgetBase;
?
/* update requist functions */
typedef void(*Update)(CCgraphicWidgetBase);
typedef void(*Hide)(CCgraphicWidgetBase);
typedef void(*Show)(CCgraphicWidgetBase);
?
?
typedef struct{Update ? ?  update;Hide ? ? ?  hide;Show ? ? ?  show;
}CCGraphicWidgetCommonOperation;
?
typedef struct
{CCGraphicWidgetCommonOperation  common;void (*switchToIndex)(CCGraphic_Menu*, uint8_t index);void (*enabled_showAnimations)(CCGraphic_Menu*, uint8_t enabled);void (*setIcon)(CCGraphic_Menu*, CCGraphic_Image* image, uint8_t size);void (*showIcon)(CCGraphic_Menu*);void (*hideIcon)(CCGraphic_Menu*);CCGraphic_Menu* (*enterSub)(CCGraphic_Menu*);CCGraphic_Menu* (*backParent)(CCGraphic_Menu*);
}CCGraphic_MenuOperations;
?
typedef struct __CCGraphic_Menu{// 菜單項數(shù)組CCGraphic_MenuItem* ? ? ? ? menuItemArrays;// 菜單項數(shù)組個數(shù)uint8_t ? ? ? ? ? ? ? ? ? ? menuArraySize;// 內(nèi)部主控件CCGraphicTextEdit* ? ? ? ?  internelTextEdit;// 動畫負責的結構體CCGraphic_MenuAnimations* ? animation_holder;// 操作CCGraphic_MenuOperations ?  operations;// 當前維護的其他信息uint8_t ? ? ? ? ? ? ? ? ? ? current_offset;uint8_t ? ? ? ? ? ? ? ? ? ? enabled_animations;CCGraphic_Image* ? ? ? ? ?  icons_sources;uint8_t ? ? ? ? ? ? ? ? ? ? icon_size;uint8_t ? ? ? ? ? ? ? ? ? ? icon_state;
}CCGraphic_Menu;

任務:你可以改進這個抽象!你可以看到零碎一地的變量成員不太美觀!

進一步談論我上面給出的代碼——繼承

讓我們進一步討論更多的概念,上面的代碼出現(xiàn)了一個很有意思的片段

typedef void* CCgraphicWidgetBase;
?
/* update requist functions */
typedef void(*Update)(CCgraphicWidgetBase);
typedef void(*Hide)(CCgraphicWidgetBase);
typedef void(*Show)(CCgraphicWidgetBase);
?
?
typedef struct{Update ? ?  update;Hide ? ? ?  hide;Show ? ? ?  show;
}CCGraphicWidgetCommonOperation;
?
typedef struct
{CCGraphicWidgetCommonOperation  common;void (*switchToIndex)(CCGraphic_Menu*, uint8_t index);void (*enabled_showAnimations)(CCGraphic_Menu*, uint8_t enabled);void (*setIcon)(CCGraphic_Menu*, CCGraphic_Image* image, uint8_t size);void (*showIcon)(CCGraphic_Menu*);void (*hideIcon)(CCGraphic_Menu*);CCGraphic_Menu* (*enterSub)(CCGraphic_Menu*);CCGraphic_Menu* (*backParent)(CCGraphic_Menu*);
}CCGraphic_MenuOperations;

仔細研究一下,你會發(fā)現(xiàn),我們似乎復用了一個結構體:CCGraphicWidgetCommonOperation,也就是組件Widget的通用操作。為了理解這個特征,我們先不著急,實現(xiàn)一個完全面對對象的,一個簡單的文本編輯器

實現(xiàn)一個面對對象的文本編輯器

#ifndef CCGraphic_TextEdit_H
#define CCGraphic_TextEdit_H
#include "Graphic/widgets/common/CCGraphic_WidgetBase.h"
#include "Graphic/base/CCGraphic_Point/CCGraphic_Point.h"
#include "Graphic/widgets/common/CCGraphic_Size/CCGraphic_Size.h"
#include "Graphic/widgets/common/CCGraphic_WidgetBase.h"
#include "Graphic/widgets/base/CCGraphic_TextItem/CCGraphic_TextItem.h"
#include "Graphic/widgets/base/CCGraphic_TextItem/CCGraphic_TextConfig.h"
typedef struct __CCGraphicTextEdit CCGraphicTextEdit; ?
// 前向聲明:定義一個名為 `CCGraphicTextEdit` 的結構體類型。 ?
?
typedef struct { ?CCGraphicWidgetCommonOperation operation; ?// 控件通用操作,提供基本控件功能。 ?
?void (*appendText)(CCGraphicTextEdit*, char* appendee); ?// 函數(shù)指針:向文本控件追加文本。 ?
?void (*setText)(CCGraphicTextEdit*, char* text); ?// 函數(shù)指針:設置控件內(nèi)的完整文本內(nèi)容。 ?
?void (*newLineText)(CCGraphicTextEdit*, char* text); ?// 函數(shù)指針:在控件中新起一行并寫入文本。 ?
?void (*clear)(CCGraphicTextEdit*); ?// 函數(shù)指針:清空控件中的文本。 ?
?void (*relocate)(CCGraphicTextEdit*, CCGraphic_Point p, CCGraphic_Size size); ?// 函數(shù)指針:重新定位控件位置并調(diào)整控件尺寸。 ?
?
} CCGraphicTextEdit_SupportiveOperations; ?
// 結構體 `CCGraphicTextEdit_SupportiveOperations`:定義文本控件支持的操作集合。 ?
?
typedef struct __CCGraphicTextEdit { ?uint8_t acquired_stepped_update; ?// 標記是否啟用分步更新機制的標志變量。 ?
?CCDeviceHandler* borrowed_device; ?// 設備處理器指針,用于管理外部設備資源。 ?
?CCGraphicTextEdit_SupportiveOperations operations; ?// 文本控件支持操作的集合。 ?
?CCGraphic_AsciiTextItem* handle; ?// 控件中的具體文本項句柄,用于操作字符顯示內(nèi)容。 ?
?
} CCGraphicTextEdit; ?
// 結構體 `CCGraphicTextEdit`:定義文本控件的屬性與操作。 ?
?
void CCGraphic_init_CCGraphicTextEdit( ?CCGraphicTextEdit* text_self, ?CCDeviceHandler* handler, ?CCGraphic_AsciiTextItem* inited ?
); ?
// 函數(shù)聲明:初始化 `CCGraphicTextEdit` 控件,傳入控件對象、設備處理器和已初始化的文本項。 ?
#endif

你可能會問,怎么看起來這么奇怪,我們應該如何調(diào)用功能呢?你看,這就是思維沒有轉(zhuǎn)變過來,筆者想要說的是,現(xiàn)在功能被集成進入了結構體,意味著,我們想要調(diào)用的不叫函數(shù)了,是一個結構體的方法。

static void __helper_on_set_text(CCGraphicTextEdit* edit, char* sources, uint32_t shown_time)
{edit->operations.setText(edit, sources);HAL_Delay(shown_time * 1000);edit->operations.clear(edit);
}

看到了嗎?當我們想要設置文本的時候,不是

CCGraphicTextEdit_setText(edit, sources);

而是

edit->operations.setText(edit, sources);

看起來好像沒什么區(qū)別,我想說的是,你現(xiàn)在不知道,也沒法去引用一個函數(shù),叫“給一個是CCGraphicTextEdit的結構體設置文本”的函數(shù),你找不到,我藏起來了(笑),而是,一個屬于CCGraphicTextEdit這個類的對象可以被設置文本,文本是sources,這就是面對對象的設計思考范式。換而言之,一個CCGraphicTextEdit的對象可以設置文本,他能設置文本而且優(yōu)先的投射到繪圖設備上,而你完全不知道底下發(fā)生了什么,只知道這樣做一定沒有問題!

在源文件中,我們才將如何實現(xiàn)暴露出來

#include "Graphic/widgets/components/CCGraphic_TextEdit/CCGraphic_TextEdit.h"
#include "Graphic/widgets/base/CCGraphic_TextItem/CCGraphic_TextItem.h"
#include "Graphic/CCGraphic_device_adapter.h"
?
static void __pvt_update_text(CCGraphicTextEdit* text_self) ?
// 靜態(tài)函數(shù):更新控件所依賴的設備內(nèi)容。 ?
{text_self->borrowed_device->operations.update_device_function(text_self->borrowed_device ?// 調(diào)用設備的更新函數(shù),使文本控件的內(nèi)容刷新顯示。 ?);
}
?
static void __pvt_show(CCGraphicTextEdit* text_self) ?
// 靜態(tài)函數(shù):繪制并顯示文本控件內(nèi)容。 ?
{CCGraphicWidget_drawAsciiTextItem(text_self->borrowed_device, text_self->handle ?// 繪制文本控件的內(nèi)容。 ?);if(text_self->acquired_stepped_update) ?// 如果啟用了分步更新,則執(zhí)行設備更新。 ?__pvt_update_text(text_self);
}
?
static void __pvt_hide(CCGraphicTextEdit* text_self) ?
// 靜態(tài)函數(shù):隱藏控件,即清除其顯示區(qū)域。 ?
{text_self->borrowed_device->operations.clearArea_function(text_self->borrowed_device, text_self->handle->tl_point.x, ?text_self->handle->tl_point.y, ?text_self->handle->TexthandleSize.width, ?text_self->handle->TexthandleSize.height ?// 清除控件所在區(qū)域的內(nèi)容。 ?);__pvt_update_text(text_self);
}
?
static void __pvt_clear_text(CCGraphicTextEdit* text_self) ?
// 靜態(tài)函數(shù):清除控件中的文本內(nèi)容。 ?
{CCGraphic_Point tl = text_self->handle->tl_point; ?CCGraphic_Size size = text_self->handle->TexthandleSize; ?// 獲取控件左上角坐標和尺寸,用于清除操作。 ?
?text_self->borrowed_device->operations.clearArea_function(text_self->borrowed_device, tl.x, tl.y, size.width, size.height ?// 執(zhí)行清除操作。 ?);__pvt_update_text(text_self);
}
?
static void __pvt_append_text(CCGraphicTextEdit* text_self, char* text) ?
// 靜態(tài)函數(shù):向控件追加文本。 ?
{CCGraphicWidget_AsciiTextItem_setAsciiText(text_self->handle, text); ?// 設置追加的文本內(nèi)容。 ?__pvt_show(text_self); ?// 顯示控件內(nèi)容。 ?
}
?
static void __pvt_newLine_text(CCGraphicTextEdit* text_self, char* text) ?
// 靜態(tài)函數(shù):在控件中新建一行并寫入文本。 ?
{CCGraphic_Point new_begin = ?CCGraphicWidget_AsciiTextItem_on_newLine_point(text_self->handle); ?// 獲取新行起始點坐標。 ?
?CCGraphicWidget_AsciiTextItem_setAsciiText(text_self->handle, text); ?// 設置文本內(nèi)容。 ?
?CCGraphicWidget_AsciiTextItem_setIndexedPoint(text_self->handle, &new_begin); ?// 更新文本項的繪制位置。 ?
?__pvt_show(text_self); ?// 顯示控件內(nèi)容。 ?
}
?
static void __pvt_setText(CCGraphicTextEdit* text_self, char* text) ?
// 靜態(tài)函數(shù):設置控件的完整文本內(nèi)容。 ?
{__pvt_clear_text(text_self); ?// 清除原有內(nèi)容。 ?
?CCGraphicWidget_AsciiTextItem_setIndexedPoint(text_self->handle, &(text_self->handle->tl_point) ?// 重置文本繪制位置為控件起點。 ?);
?CCGraphicWidget_AsciiTextItem_setAsciiText(text_self->handle, text); ?// 設置新的文本內(nèi)容。 ?
?__pvt_show(text_self); ?// 顯示控件內(nèi)容。 ?
}
?
static void __pvt_relocate(CCGraphicTextEdit* edit, CCGraphic_Point p, CCGraphic_Size size) ?
// 靜態(tài)函數(shù):重新定位控件位置并調(diào)整尺寸。 ?
{__pvt_hide(edit); ?// 隱藏控件內(nèi)容。 ?
?CCGraphicWidget_AsciiTextItem_relocate(edit->handle, p, size); ?// 重新設置控件位置和尺寸。 ?
}
?
void CCGraphic_init_CCGraphicTextEdit( ?CCGraphicTextEdit* text_self, ?CCDeviceHandler* handler, ?CCGraphic_AsciiTextItem* inited ?
) ?
// 初始化函數(shù):設置文本編輯控件的初始狀態(tài)。 ?
{text_self->acquired_stepped_update = 0; ?// 初始化為未啟用分步更新。 ?
?text_self->borrowed_device = handler; ?// 綁定設備處理器。 ?
?text_self->handle = inited; ?// 設置文本項句柄。 ?
?text_self->operations.appendText = __pvt_append_text; ?text_self->operations.clear = __pvt_clear_text; ?text_self->operations.newLineText = __pvt_newLine_text; ?text_self->operations.setText = __pvt_setText; ?text_self->operations.relocate = __pvt_relocate; ?// 綁定控件的各類操作函數(shù)。 ?
?text_self->operations.operation.hide = (Hide)__pvt_hide; ?text_self->operations.operation.show = (Show)__pvt_show; ?text_self->operations.operation.update = (Update)__pvt_update_text; ?// 綁定通用控件操作。 ?
}

可以看到,代碼被分成了一層一層的,關心哪一個方法,只需要進入對應的方法查看即可。

所以,什么是繼承

繼承允許一個類從另一個類中獲取屬性和方法,從而實現(xiàn)代碼復用和邏輯擴展。也就是說,我們認為繼承表達了“一個對象是另一個對象”的陳述。比如說。

typedef struct { ?CCGraphicWidgetCommonOperation operation; ?// 控件通用操作,提供基本控件功能。 ?
?void (*appendText)(CCGraphicTextEdit*, char* appendee); ?// 函數(shù)指針:向文本控件追加文本。 ?
?void (*setText)(CCGraphicTextEdit*, char* text); ?// 函數(shù)指針:設置控件內(nèi)的完整文本內(nèi)容。 ?
?void (*newLineText)(CCGraphicTextEdit*, char* text); ?// 函數(shù)指針:在控件中新起一行并寫入文本。 ?
?void (*clear)(CCGraphicTextEdit*); ?// 函數(shù)指針:清空控件中的文本。 ?
?void (*relocate)(CCGraphicTextEdit*, CCGraphic_Point p, CCGraphic_Size size); ?// 函數(shù)指針:重新定位控件位置并調(diào)整控件尺寸。 ?
?
} CCGraphicTextEdit_SupportiveOperations; ?

表達了CCGraphicTextEdit的功能集合是CCGraphicWidget的一個超集,他不光擁有一個Widget該有的操作,而且,還有自己跟Widget獨有的操作,這就是繼承的力量——復用接口,甚至可以是實現(xiàn)!

重申我們對菜單的抽象

根據(jù)最之前的描述,菜單本身應該是一個樹狀的結構,你可以看到:

抽象菜單項目

#ifndef CCGraphic_MenuItem_H
#define CCGraphic_MenuItem_H
#include "Graphic/CCGraphic_common.h"
/* This version we use simple menu Item */
?
/* announced the menu type for the further usage */ ?
// 預聲明 `CCGraphic_Menu` 類型,用于菜單關聯(lián)。 ?
?
typedef struct __CCGraphic_Menu CCGraphic_Menu; ?
// 結構體 `CCGraphic_Menu` 的前向聲明,以便在結構中使用指針引用該類型。 ?
?
#define NO_SUB_MENU (NULL) ?
// 定義宏 `NO_SUB_MENU` 表示沒有子菜單,為空指針。 ?
?
typedef struct __CCGraphic_MenuItem { ?char* text; ?// 菜單項顯示的文本內(nèi)容。 ?
?CCGraphic_Menu* subMenu; ?// 指向子菜單的指針,若無子菜單則為 `NO_SUB_MENU`。 ?
?CCGraphic_Menu* parentMenu; ?// 指向父菜單的指針,用于返回或?qū)蛹壙刂啤??
} CCGraphic_MenuItem; ?
// 定義菜單項結構體 `CCGraphic_MenuItem`,包含菜單文字、子菜單及父菜單指針。 ?
?
void CCGraphic_MenuItem_register_menuItem( ?CCGraphic_MenuItem* item, ?// 菜單項指針,用于注冊菜單項。 ?
?CCGraphic_Menu* parentMenu, ?// 父菜單指針,將菜單項附加到此菜單下。 ?
?char* text, ?// 菜單項文本內(nèi)容。 ?
?CCGraphic_Menu* subMenu ?// 子菜單指針,可為 `NO_SUB_MENU`。 ?
); ?
// 函數(shù)聲明:將菜單項注冊到指定父菜單下,同時設置菜單項文本和子菜單。 ?
#endif

提示:需要做callback?(用戶明確選擇了這個菜單項目)試一下在CCGraphic_MenuItem中添加抽象!完成你的代碼!

抽象菜單動畫

typedef struct __CCGraphic_MenuAnimations CCGraphic_MenuAnimations; ?
// 前向聲明 `CCGraphic_MenuAnimations` 結構體,表示菜單動畫的管理結構。 ?
?
typedef void (*DoByStep)(CCGraphic_MenuAnimations*); ?
// 定義一個函數(shù)指針類型 `DoByStep`,指向以 `CCGraphic_MenuAnimations*` 為參數(shù)的函數(shù),
// 該函數(shù)用于執(zhí)行逐步動畫操作。 ?
?
typedef struct { ?DoByStep doByStep; ?// 操作結構體,包含逐步執(zhí)行動畫的函數(shù)指針。 ?
} CCGraphic_MenuAnimationsOperations; ?
// 定義 `CCGraphic_MenuAnimationsOperations` 結構體,封裝了逐步動畫執(zhí)行的操作。 ?
?
/*this struct shouldn't be registered by programmersit shoule be registered by program, so no interface ispubliced!
*/ ?
// 該結構體不應由程序員手動注冊,而是由程序自動注冊,因此沒有提供公開接口。 ?
?
typedef struct __CCGraphic_MenuAnimations { ?/* animating rectangle */ ?// 定義菜單動畫的結構體。 ?
?CCDeviceHandler* handler; ?// 設備處理器,用于控制設備的操作。 ?
?CCGraphic_Point tl_point; ?// 動畫的起始點(左上角坐標)。 ?
?CCGraphic_Size animationOffsetSize; ?// 動畫的偏移尺寸,用于表示動畫區(qū)域的大小。 ?
?int16_t x_step; ?// x軸每步移動的像素值,用于控制動畫的水平位移。 ?
?int16_t y_step; ?// y軸每步移動的像素值,用于控制動畫的垂直位移。 ?
?CCGraphic_MenuAnimationsOperations op; ?// 操作對象,包含執(zhí)行逐步動畫的函數(shù)指針。 ?
?uint8_t is_doing; ?// 標志位,表示動畫是否正在進行中。 ?
} CCGraphic_MenuAnimations; ?
// 定義菜單動畫結構體,封裝了動畫的狀態(tài)、操作及設備控制。 ?

初始化一個動畫的辦法是:

static void __pvt_init_animations( ?CCGraphic_Menu* ? ? ? ? ? ? menu, ?CCGraphic_MenuAnimations* ? animations ?
) { ?/* no animations are registered */ ?// 如果沒有提供動畫對象,直接返回。 ?if (animations == NULL) { ?return; ?}
?// 獲取菜單中的文本編輯項句柄,進行后續(xù)動畫初始化。 ?CCGraphic_AsciiTextItem* internelTextEdit = menu->internelTextEdit->handle; ?
?/* calculate the animations holding size */ ?// 計算動畫的大小,首先設置動畫起始點為文本編輯項的起始點。 ?animations->tl_point = internelTextEdit->tl_point; ?
?// 設置動畫的高度為字體的大小(通過 `__fetch_font_size` 獲取字體的高度)。 ?animations->animationOffsetSize.height = __fetch_font_size(internelTextEdit->font_size).height; ?
?// 設置動畫的寬度為文本處理器的寬度。 ?animations->animationOffsetSize.width = internelTextEdit->TexthandleSize.width; ?
?// 設置設備處理器,使用菜單中的文本編輯項借用的設備。 ?animations->handler = menu->internelTextEdit->borrowed_device; ?
?// 設置每步的水平和垂直步長(默認值)。 ?animations->x_step = _DEFAULT_X_STEP; ?animations->y_step = _DEFAULT_Y_STEP; ?
?// 設置執(zhí)行逐步動畫操作的函數(shù)指針,指向 `__pvt_doByStep` 函數(shù)。 ?animations->op.doByStep = __pvt_doByStep; ?
?/* set state */ ?// 設置動畫狀態(tài)為未開始。 ?animations->is_doing = 0; ?
} ?

對于逐步開始動畫的辦法是

/* do by steps */
static void __pvt_doByStep(CCGraphic_MenuAnimations* animations) ?
{ ?// 如果動畫尚未開始(is_doing 為 0),則直接返回,避免不必要的操作。 ?if (!animations->is_doing) return; ?
?// 使用設備的操作對象反轉(zhuǎn)(擦除)動畫區(qū)域,傳入當前動畫的起始位置(tl_point)和尺寸。 ?animations->handler->operations.reverseArea_function( ?animations->handler, ?animations->tl_point.x, animations->tl_point.y, ?animations->animationOffsetSize.width, ?animations->animationOffsetSize.height ?); ?
?// 更新動畫的起始點(左上角坐標),按水平步長(x_step)和垂直步長(y_step)更新。 ?animations->tl_point.x += animations->x_step; ?animations->tl_point.y += animations->y_step; ?
?// 再次調(diào)用反轉(zhuǎn)(擦除)區(qū)域,傳入更新后的動畫位置和尺寸。 ?animations->handler->operations.reverseArea_function( ?animations->handler, ?animations->tl_point.x, animations->tl_point.y, ?animations->animationOffsetSize.width, ?animations->animationOffsetSize.height ?); ?
?// 調(diào)用更新設備函數(shù),刷新屏幕以顯示動畫效果。 ?animations->handler->operations.update_device_function( ?animations->handler ?); ?
} ?

看到了嗎,非必要不調(diào)用刷新設備的操作就在這里體現(xiàn)了。當然,當我們配置不需要動畫的時候

static void __pvt_do_as_immediate(CCGraphic_MenuAnimations* animations, CCGraphic_Point* ? ? ?  end_tpl)
{if(!animations->is_doing) return;animations->handler->operations.reverseArea_function(animations->handler, animations->tl_point.x, animations->tl_point.y,animations->animationOffsetSize.width, animations->animationOffsetSize.height);animations->tl_point = *end_tpl;animations->handler->operations.reverseArea_function(animations->handler, animations->tl_point.x, animations->tl_point.y,animations->animationOffsetSize.width, animations->animationOffsetSize.height);animations->handler->operations.update_device_function(animations->handler);
}

直接拉到最后就好了。

實現(xiàn)菜單功能

到了真正實現(xiàn)的時候,一切反而水到渠成。

初始化我們的菜單
void CCGraphic_init_Menu(CCGraphic_Menu* ? ? ? ? ? ? blank_menu,CCGraphic_MenuItem* ? ? ? ? menuItemArrays,uint8_t ? ? ? ? ? ? ? ? ? ? menuArraySize,CCGraphicTextEdit* ? ? ? ?  configured_menu,CCGraphic_MenuAnimations* ? blank_animations,uint8_t ? ? ? ? ? ? ? ? ? ? enabled_animations 
)
{blank_menu->internelTextEdit ?  = configured_menu;blank_menu->menuItemArrays ? ?  = menuItemArrays;blank_menu->menuArraySize ? ? ? = menuArraySize;blank_menu->animation_holder ?  = blank_animations;blank_menu->current_offset ? ?  = 0;blank_menu->icon_state ? ? ? ?  = 0;blank_menu->enabled_animations = enabled_animations;
?// map the functionsblank_menu->operations.common.hide ? ?  = (Hide)__pvt_hide_CCGraphic_Menu;blank_menu->operations.common.show ? ?  = (Show)__pvt_show_CCGraphic_Menu;blank_menu->operations.common.update ?  = (Update)__pvt_update;blank_menu->operations.switchToIndex ?  = __pvt_switchIndex;blank_menu->operations.enabled_showAnimations = __pvt_setAnimationShowState_wrapper;// iconsblank_menu->operations.setIcon = __pvt_setIcon;blank_menu->operations.hideIcon = __pvt_hideIcon;blank_menu->operations.showIcon = __pvt_showIcon;blank_menu->operations.enterSub = __pvt_enterSub;blank_menu->operations.backParent = __pvt_backParent;__pvt_init_animations(blank_menu, blank_animations);
}
關于我們的圖標設置,顯示和隱藏
static void __pvt_setIcon(CCGraphic_Menu* menu, CCGraphic_Image* sources, uint8_t size) ?
{ ?// 設置菜單的圖標源和圖標數(shù)量 ?menu->icons_sources = sources; ?menu->icon_size = size; ?
?// 初始化每個圖標的尺寸和位置 ?for (uint8_t i = 0; i < menu->icon_size; i++) { ?// 設置圖標的高度和寬度 ?sources[i].image_size.height = ICON_HEIGHT; ?sources[i].image_size.width = ICON_WIDTH; ?
?// 設置每個圖標的位置,`y` 方向依次排列 ?sources[i].point.x = 0; ?sources[i].point.y = i * ICON_HEIGHT; ?} ?
?// 顯示圖標 ?__pvt_showIcon(menu); ?
} ?
?
static void __pvt_showIcon(CCGraphic_Menu* menu) ?
{ ?// 如果沒有圖標源,則不執(zhí)行任何操作 ?if (!menu->icons_sources) return; ?// 設置圖標的狀態(tài)為顯示(1) ?menu->icon_state = 1; ?CCGraphic_Point tlp; ?CCGraphic_Size _size; ?// 獲取顯示圖標的位置和大小 ?__pvt_providePoint(menu, &tlp, 1); ?__pvt_provideSize(menu, &_size, 1); ?// 設置動畫的顯示狀態(tài)為 0(關閉動畫) ?__pvt_setAnimationShowState(menu->animation_holder, 0); ?// 將菜單項的文本編輯區(qū)域重新定位到指定的位置和大小 ?menu->internelTextEdit->operations.relocate(menu->internelTextEdit, tlp, _size); ?// 遍歷圖標源,逐一繪制每個圖標 ?for (uint8_t i = 0; i < menu->icon_size; i++) { ?CCGraphicWidget_draw_image( ?menu->internelTextEdit->borrowed_device, ?&menu->icons_sources[i] ?); ?} ?// 設置動畫的顯示狀態(tài)為 1(啟用動畫) ?__pvt_setAnimationShowState(menu->animation_holder, 1); ?// 僅顯示文本編輯器 ?__pvt_show_textEditOnly(menu); ?
} ?
?
static void __pvt_hideIcon(CCGraphic_Menu* menu) ?
{ ?// 如果沒有圖標源,則不執(zhí)行任何操作 ?if (!menu->icons_sources) return; ?CCGraphic_Point tlp; ?CCGraphic_Size _size; ?// 設置圖標的狀態(tài)為隱藏(0) ?menu->icon_state = 0; ?// 獲取隱藏圖標的位置和大小 ?__pvt_providePoint(menu, &tlp, 0); ?__pvt_provideSize(menu, &_size, 0); ?// 設置動畫的顯示狀態(tài)為 0(關閉動畫) ?__pvt_setAnimationShowState(menu->animation_holder, 0); ?// 將菜單項的文本編輯區(qū)域重新定位到指定的位置和大小 ?menu->internelTextEdit->operations.relocate(menu->internelTextEdit, tlp, _size); ?// 清除圖標區(qū)域 ?menu->internelTextEdit->borrowed_device->operations.clearArea_function( ?menu->internelTextEdit->borrowed_device, ?0, 0, ICON_WIDTH, ICON_HEIGHT * menu->icon_size ?); ?// 僅顯示文本編輯器 ?__pvt_show_textEditOnly(menu); ?
} ?

圖標的繪制就是讓位子繪制,清除掉重新繪制這個思路。

菜單本體功能
static void __pvt_update(CCGraphic_Menu* menu)
{// 調(diào)用文本編輯器的更新操作,刷新菜單顯示menu->internelTextEdit->operations.operation.update(menu->internelTextEdit);
}
?
// 更新動畫狀態(tài)
static void __pvt_setAnimationShowState(CCGraphic_MenuAnimations* animations, uint8_t is_doing)
{// 如果動畫狀態(tài)沒有變化,直接返回if(is_doing == animations->is_doing){return;}// 如果動畫正在進行,先逆向繪制區(qū)域,清除之前的顯示animations->handler->operations.reverseArea_function(animations->handler, animations->tl_point.x, animations->tl_point.y,animations->animationOffsetSize.width, animations->animationOffsetSize.height);// 更新動畫狀態(tài)animations->is_doing = is_doing;// 更新設備,刷新顯示animations->handler->operations.update_device_function(animations->handler);
}
?
/*以下是顯示/隱藏圖標時,提供布局計算的函數(shù)
*/
static void __pvt_providePoint(CCGraphic_Menu* menu, CCGraphic_Point* p, uint8_t icons_enabled)
{// 根據(jù)是否啟用圖標,設置圖標顯示的起始位置p->x = icons_enabled ? ICON_WIDTH : 0;p->y = 0;
}
?
static void __pvt_provideSize(CCGraphic_Menu* menu, CCGraphic_Size* size, uint8_t icons_enabled
){// 根據(jù)是否啟用圖標,調(diào)整文本區(qū)域的寬度和高度size->width = menu->internelTextEdit->handle->TexthandleSize.width - (icons_enabled ? ICON_HEIGHT : 0);size->height = menu->internelTextEdit->handle->TexthandleSize.height;
}
?
// 獲取當前菜單項是否有子菜單
static inline CCGraphic_Menu* __pvt_current_owns_subMenu(CCGraphic_Menu* menu)
{return  menu->menuItemArrays[menu->current_offset].subMenu;
}
?
// 獲取當前菜單項的父菜單
static inline CCGraphic_Menu* __pvt_owns_parent_current(CCGraphic_Menu* menu)
{return  menu->menuItemArrays[menu->current_offset].parentMenu;
}
?
// 僅顯示文本編輯器的內(nèi)容,更新菜單顯示
void __pvt_show_textEditOnly(CCGraphic_Menu* menu)
{// 如果菜單沒有項,則直接返回if(menu->menuArraySize == 0){return;}// 設置動畫狀態(tài)為不顯示__pvt_setAnimationShowState(menu->animation_holder, 0);// 設置文本編輯器的內(nèi)容,顯示第一項菜單CCGraphicTextEdit* edit = menu->internelTextEdit;edit->operations.setText(edit, menu->menuItemArrays[0].text);// 顯示后續(xù)菜單項for(uint8_t i = 1; i < menu->menuArraySize; i++){edit->operations.newLineText(edit, menu->menuItemArrays[i].text);}// 設置動畫狀態(tài)為顯示__pvt_setAnimationShowState(menu->animation_holder, 1); ? ?
}
?
// 隱藏菜單和圖標
void __pvt_hide_CCGraphic_Menu(CCGraphic_Menu* menu)
{// 隱藏圖標__pvt_hideIcon(menu);// 隱藏文本編輯器menu->internelTextEdit->operations.operation.hide(menu->internelTextEdit);// 獲取動畫控制器CCGraphic_MenuAnimations* animation = menu->animation_holder;// 如果沒有動畫控制器,則返回if(!animation) return;// 如果動畫正在進行,則停止動畫if(animation->is_doing){__pvt_setAnimationShowState(animation, 0);}
}
?
/* 繪制菜單顯示 */
void __pvt_show_CCGraphic_Menu(CCGraphic_Menu* menu)
{// 僅顯示文本編輯器內(nèi)容__pvt_show_textEditOnly(menu); ? 
}
?
// 執(zhí)行動畫,逐步更新菜單位置直到目標位置
void __pvt_do_stepped_animate(CCGraphic_MenuAnimations* animations, CCGraphic_Point* end_tl_p 
)
{// 如果動畫步長為負,表示需要向下移動if(animations->y_step < 0){// 逐步向下執(zhí)行動畫,直到達到目標位置while(animations->tl_point.y > end_tl_p->y){__pvt_doByStep(animations);  // 執(zhí)行單步動畫
#ifdef REQ_ANIMATION_DELAY// 延時,模擬動畫效果__device_delay(ANIMATION_DELAY_MS);
#endif}}// 如果動畫步長為正,表示需要向上移動else{// 逐步向上執(zhí)行動畫,直到達到目標位置while(animations->tl_point.y < end_tl_p->y){__pvt_doByStep(animations);  // 執(zhí)行單步動畫
#ifdef REQ_ANIMATION_DELAY// 延時,模擬動畫效果__device_delay(ANIMATION_DELAY_MS);
#endif} ? ? ? ?}}
關于切換focus的菜單和進入父子菜單的函數(shù)
// 切換菜單項索引并執(zhí)行動畫
static void __pvt_switchIndex(CCGraphic_Menu* menu, uint8_t index)
{// 如果索引沒有變化,不做任何操作if(index == menu->current_offset) return;
?// 如果新索引大于當前索引,表示需要向下移動if(index > menu->current_offset){// 如果當前動畫步長為負,改為正值if(menu->animation_holder->y_step < 0){menu->animation_holder->y_step = -menu->animation_holder->y_step;}}// 如果新索引小于當前索引,表示需要向上移動else{// 如果當前動畫步長為正,改為負值if(menu->animation_holder->y_step > 0){menu->animation_holder->y_step = -menu->animation_holder->y_step;}}// 更新當前菜單項的索引menu->current_offset = index;// 計算目標位置CCGraphic_Point end_tlp;end_tlp = menu->animation_holder->tl_point; end_tlp.y = index * menu->animation_holder->animationOffsetSize.height;// 如果啟用了動畫,執(zhí)行逐步動畫if(menu->enabled_animations)__pvt_do_stepped_animate(menu->animation_holder, &end_tlp);else// 否則,立即執(zhí)行動畫__pvt_do_as_immediate(menu->animation_holder, &end_tlp);
}
?
// 進入子菜單并顯示子菜單的內(nèi)容
static CCGraphic_Menu* __pvt_enterSub(CCGraphic_Menu* parentMenu)
{// 緩存父菜單的圖標狀態(tài)uint8_t cached_icon_state = parentMenu->icon_state;// 獲取父菜單的子菜單CCGraphic_Menu* subone = __pvt_current_owns_subMenu(parentMenu);// 如果沒有子菜單,返回NULLif(!subone) return NULL;// 隱藏當前菜單parentMenu->operations.common.hide(parentMenu);// 恢復父菜單的圖標狀態(tài)parentMenu->icon_state = cached_icon_state;// 如果子菜單有圖標,顯示圖標,否則顯示子菜單if(subone->icon_state){subone->operations.showIcon(subone);}else{subone->operations.common.show(subone);}// 返回子菜單return subone;
}
?
// 返回父菜單并顯示父菜單的內(nèi)容
static CCGraphic_Menu* __pvt_backParent(CCGraphic_Menu* subMenu)
{// 緩存子菜單的圖標狀態(tài)uint8_t cached_icon_state = subMenu->icon_state;// 獲取子菜單的父菜單CCGraphic_Menu* parentMenu = __pvt_owns_parent_current(subMenu);// 如果沒有父菜單,返回NULLif(!parentMenu) return NULL;// 隱藏當前子菜單subMenu->operations.common.hide(subMenu);// 恢復子菜單的圖標狀態(tài)subMenu->icon_state = cached_icon_state;// 如果父菜單有圖標,顯示圖標,否則顯示父菜單if(parentMenu->icon_state){parentMenu->operations.showIcon(parentMenu);}else{parentMenu->operations.common.show(parentMenu);}// 返回父菜單return parentMenu;
}

完整的測試文件

現(xiàn)在來看看完整的測試文件!

#include "Test/OLED_TEST/oled_test.h"
#include "Test/GraphicTest/graphic_test.h"
#include "Graphic/widgets/components/CCGraphic_TextEdit/CCGraphic_TextEdit.h"
void test_oled_iic_functionalities()
{OLED_Handle handle;user_init_hard_iic_oled_handle(&handle);test_set_pixel_line(&handle, 1, 2);HAL_Delay(1000);test_clear(&handle);test_set_pixel_line(&handle, 2, 1);HAL_Delay(1000);test_clear(&handle);
}
?
void test_oled_spi_functionalities()
{OLED_Handle handle;user_init_hard_spi_oled_handle(&handle);test_set_pixel_line(&handle, 1, 2);HAL_Delay(1000);test_clear(&handle);test_set_pixel_line(&handle, 2, 1);HAL_Delay(1000);test_clear(&handle);
}
?
static void __helper_on_set_text(CCGraphicTextEdit* edit, char* sources, uint32_t shown_time)
{edit->operations.setText(edit, sources);HAL_Delay(shown_time * 1000);edit->operations.clear(edit);
}
?
#define SET_TEXT_CONV(SRC, SECS) do{ sources = SRC;\__helper_on_set_text(&edit, sources, SECS);}while(0)
?
static void __test_common(CCDeviceHandler* handler)
{CCGraphicTextEdit ? edit;CCGraphic_AsciiTextItem item;CCGraphic_Point p;p.x = 0;p.y = 0;CCGraphic_Size acceptablesize = CCGraphicWidget_MaxAcceptable_Size(handler);CCGraphicWidget_init_AsciiTextItem(&item, p, acceptablesize, ASCII_6x8);CCGraphic_init_CCGraphicTextEdit(&edit, handler, &item);edit.acquired_stepped_update = 1;char* sources;SET_TEXT_CONV("Hello! Welcome CCGraphic SimpleTest!", 5);SET_TEXT_CONV("If you see this sentences, ""it means that you have passed the GraphicTest""and congratulations!", 7);
?SET_TEXT_CONV("Graphic Test On Base begin", 4);SET_TEXT_CONV("Test Points", 4);on_test_draw_points(handler);HAL_Delay(1000);SET_TEXT_CONV("Test Lines", 4);on_test_draw_line(handler);HAL_Delay(1000);SET_TEXT_CONV("Test Circles", 4);on_test_draw_circle(handler);HAL_Delay(1000);SET_TEXT_CONV("Test Rectangle", 4);on_test_draw_rectangle(handler);HAL_Delay(1000);SET_TEXT_CONV("Test Triangle", 4);on_test_draw_triangle(handler);HAL_Delay(1000);SET_TEXT_CONV("Test Ellipse", 4);on_test_draw_ellipse(handler);HAL_Delay(1000);SET_TEXT_CONV("Test Arc", 4);on_test_draw_arc(handler);HAL_Delay(1000);SET_TEXT_CONV("Graphic Test On Base end", 4);SET_TEXT_CONV("Graphic Test On widget begin", 4);SET_TEXT_CONV("Test Image Drawing", 4);
?/* widget test */on_test_draw_image(handler);HAL_Delay(1000);SET_TEXT_CONV("Test Ascii Draw", 4);on_test_draw_ascii(handler);HAL_Delay(1000);SET_TEXT_CONV("Graphic Test On widget end", 4);SET_TEXT_CONV("Graphic Test On component begin", 4);SET_TEXT_CONV("Test TextEdit", 4);/* components test */on_test_component_textEdit_test(handler);HAL_Delay(1000);SET_TEXT_CONV("Test Frame", 4);on_test_component_frame_test(handler);HAL_Delay(1000);SET_TEXT_CONV("Test Menu", 4);on_test_component_menu(handler);HAL_Delay(1000);SET_TEXT_CONV("Graphic Test On component end", 4);SET_TEXT_CONV("Finish Testing, enjoy!", 4);
}
?
?
void test_graphic_hardiic_functionalities()
{CCDeviceHandler handler;on_test_init_hardiic_oled(&handler);
?__test_common(&handler);
}
?
void test_graphic_soft_spi_functionalities()
{CCDeviceHandler handler;on_test_init_softspi_oled(&handler);
?__test_common(&handler);
}
?
?
void test_graphic_hard_spi_functionalities()
{CCDeviceHandler handler;on_test_init_hardspi_oled(&handler);
?__test_common(&handler);
}

效果就是這個完整的測試視頻:

完整測試視頻

目錄導覽

總覽

協(xié)議層封裝

OLED設備封裝

繪圖設備抽象

基礎圖形庫封裝

基礎組件實現(xiàn)

動態(tài)菜單組件實現(xiàn)

http://www.risenshineclean.com/news/41185.html

相關文章:

  • 國外超酷設計網(wǎng)站游戲推廣
  • 如何做服裝的微商城網(wǎng)站重慶森林經(jīng)典臺詞獨白
  • 云南省建設工程招標投標行業(yè)協(xié)會網(wǎng)站百度seo排名優(yōu)化教程
  • vs2010做網(wǎng)站時間控件廊坊網(wǎng)站排名優(yōu)化公司哪家好
  • readme.md做網(wǎng)站seo平臺是什么意思
  • 哪個網(wǎng)站可以做優(yōu)惠券seo技術培訓寧波
  • qq是哪個公司開發(fā)seo排名平臺
  • 特價手機網(wǎng)站建設1688seo優(yōu)化是什么
  • 網(wǎng)頁設計實訓報告實訓小結深圳百度seo整站
  • 網(wǎng)站logo怎么做最清楚惠州網(wǎng)站制作推廣
  • 廈門app網(wǎng)站建設平臺推廣是什么工作
  • 建站之星如何建網(wǎng)站sem推廣是什么
  • 哪里做企業(yè)網(wǎng)站上海seo服務
  • 天津市做網(wǎng)站的公司查淘寶關鍵詞排名軟件
  • 香港一卡通app下載鄭州seo外包顧問熱狗
  • 去哪里找做網(wǎng)站的百度競價ocpc投放策略
  • 設計導航網(wǎng)站 左側菜單欄網(wǎng)絡營銷課程論文
  • 農(nóng)產(chǎn)品網(wǎng)站如何做地推網(wǎng)易企業(yè)郵箱
  • 網(wǎng)站開發(fā)語言 排行榜關鍵詞seo公司真實推薦
  • 醫(yī)藥網(wǎng)站建設客戶的需求廈門關鍵詞排名推廣
  • 西部數(shù)碼 空間做2個網(wǎng)站什么是新媒體運營
  • 自適應手機網(wǎng)站 css愛站網(wǎng)是什么
  • 博物館文化網(wǎng)站建設青島排名推廣
  • 投訴做網(wǎng)站的電話服務器域名查詢
  • 室內(nèi)設計網(wǎng)站大全網(wǎng)seo新手教程
  • 響應式網(wǎng)站弊端互聯(lián)網(wǎng)公司
  • 池州市住房和城鄉(xiāng)建設委員會網(wǎng)站百度推廣聯(lián)系人
  • 山東安康建設項目管理有限公司網(wǎng)站北京谷歌優(yōu)化
  • 大宗商品現(xiàn)貨交易app天津seo優(yōu)化公司哪家好
  • 無錫網(wǎng)站優(yōu)化價格福鼎網(wǎng)站優(yōu)化公司