点击上方「嵌入式大杂烩」,选择「置顶公众号」第一时间查看嵌入式笔记!
上一篇分享了:分享一个有趣的库,让你学习C语言不会觉得那么枯燥。有几位小伙伴发表了自己的看法让我陷入思考。
这个是C++,和C不要搞混淆了,两种语言。
这种没意思,浪费时间。
这里简单说一下。
1、上一篇文章里,我也很明确地在文章里说EasyX是一个C++图形库呀,没说EasyX是C语言图形库。标题与C语言相关是因为初学C的确是可以用这个库来进行学习,可以在CPP文件里写C的语法做一些小程序,本篇笔记我分享的这个小程序的工程虽然是C++工程,但是我完全使用C的语法来实现。
所以这个就不用纠结了,觉得有用则拿走,没用就忽略就好。另外再说一点,初学C的朋友,去写那些课本课后小编程题,还不如学写一些小程序效果来的好一些。
2、你觉得没意思的东西可能别人觉得有意思。Easy X依赖了很多Windows平台的东西,我最近工作中用到了一个模拟器,而这个模拟器的源码恰好与这个有点相关,很巧~
我下一步还在想着看看能不能用Easy X也写一个模拟器出来。知识,只有相互碰撞,才能产生更多的想法~
废话不多说,下面进入本篇笔记正题。
这个小程序其实之前已经有分享过了:【socket应用】基于C语言的天气客户端的实现。但是之前做的比较粗糙,之前的效果是这样的:
这次我们借助Easy X来对界面进行一个简单的优化:
工程是基于VS2019地C++工程:
基于VS编写代码可能会遇到很多问题,高版本地VS比较排斥一些不安全地函数,比如使用一些socket相关的接口、还有字符串操作相关如sprintf等函数可能会编译不通过,如果编译不通过,按照提示去解决即可,如:
// 微信公众号:嵌入式大杂烩
#include "weather_ui.h"
#include "weather_data_parse.h"
int main(void)
{
Weather weather_data = {0};
struct time_data system_tim = {0};
static u_int cur_sec = 0, last_sec = 0, sec_count = 0;
/* 获取天气数据 */
GetWeather((char*)NOW_JSON, (char*)"beijing", &weather_data);
GetWeather((char*)DAILY_JSON, (char*)"beijing", &weather_data);
/* 创建绘图窗口,分辨率 640x480 */
initgraph(WINDOW_WIDTH, WINDOW_HEIGHT);
/* 设置背景 */
set_background();
while (1)
{
/* 获取本地时间 */
system_tim = get_time();
/* 第一次显示时间及天气 */
time_data_display(&system_tim);
weather_display(&weather_data);
/* 1s更新一次时间数据,1小时更新一次天气 */
cur_sec = system_tim.sec;
if (cur_sec != last_sec)
{
last_sec = cur_sec;
sec_count++;
time_data_display(&system_tim);
if (sec_count > 60 * 60)
{
sec_count = 0;
weather_display(&weather_data);
}
}
Sleep(1000);
}
closegraph();
return 0;
}
获取天气数据、初始化显示环境、显示时间日期及天气。
// 微信公众号:嵌入式大杂烩
void GetWeather(char* weather_json, char* location, Weather* result)
{
SOCKET ClientSock;
WSADATA wd;
char GetRequestBuf[256] = { 0 };
char WeatherRecvBuf[2 * 1024] = { 0 };
char GbkRecvBuf[2 * 1024] = { 0 };
int gbk_recv_len = 0;
int connect_status = 0;
/* 初始化操作sock需要的DLL */
WSAStartup(MAKEWORD(2, 2), &wd);
/* 设置要访问的服务器的信息 */
SOCKADDR_IN ServerSockAddr;
memset(&ServerSockAddr, 0, sizeof(ServerSockAddr)); // 每个字节都用0填充
ServerSockAddr.sin_family = PF_INET; // IPv4
ServerSockAddr.sin_addr.s_addr = inet_addr(WEATHER_IP_ADDR); // 心知天气服务器IP
ServerSockAddr.sin_port = htons(WEATHER_PORT); // 端口
/* 创建客户端socket */
if (-1 == (ClientSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)))
{
printf("socket error!\n");
exit(1);
}
/* 连接服务端 */
if (-1 == (connect_status = connect(ClientSock, (SOCKADDR*)&ServerSockAddr, sizeof(SOCKADDR))))
{
printf("connect error!\n");
exit(1);
}
/* 组合GET请求包 */
sprintf(GetRequestBuf, GET_REQUEST_PACKAGE, weather_json, KEY, location);
/* 发送数据到服务端 */
send(ClientSock, GetRequestBuf, strlen(GetRequestBuf), 0);
/* 接受服务端的返回数据 */
recv(ClientSock, WeatherRecvBuf, 2 * 1024, 0);
/* utf-8转为gbk */
SwitchToGbk((const unsigned char*)WeatherRecvBuf, strlen((const char*)WeatherRecvBuf), (unsigned char*)GbkRecvBuf, &gbk_recv_len);
#if DEBUG
printf("服务端返回的数据为:%s\n", GbkRecvBuf);
#endif
/* 解析天气数据并保存到结构体变量weather_data中 */
if (0 == strcmp(weather_json, NOW_JSON)) // 天气实况
{
cJSON_NowWeatherParse(GbkRecvBuf, result);
}
else if (0 == strcmp(weather_json, DAILY_JSON)) // 未来三天天气
{
cJSON_DailyWeatherParse(GbkRecvBuf, result);
}
/* 清空缓冲区 */
memset(GetRequestBuf, 0, 256);
memset(WeatherRecvBuf, 0, 2 * 1024);
memset(GbkRecvBuf, 0, 2 * 1024);
/* 关闭套接字 */
closesocket(ClientSock);
/* 终止使用 DLL */
WSACleanup();
}
代码太多,略过。文末可获取代码工程。
// 微信公众号:嵌入式大杂烩
void weather_display(Weather* weather_data)
{
char tmp_buf[50] = {0};
IMAGE pDstImg;
RECT rect;
/* 设置一些默认样式 */
setlinecolor(WHITE);
setbkcolor(BACK_GROUND_COLOR);
settextstyle(DEFAULT_FONT_HEIGHT, DEFAULT_FONT_WIDTH, DEFAULT_FONT_TYPE);
/* 分割线 */
line(0, WINDOW_HEIGHT / 2, WINDOW_WIDTH, WINDOW_HEIGHT / 2);
line(WINDOW_WIDTH / 3, WINDOW_HEIGHT / 2, WINDOW_WIDTH / 3, WINDOW_HEIGHT);
line(WINDOW_WIDTH * 2 / 3, WINDOW_HEIGHT / 2, WINDOW_WIDTH * 2 / 3, WINDOW_HEIGHT);
/* 城市名 */
settextstyle(CITY_FONT_HEIGHT, CITY_FONT_WIDTH, DEFAULT_FONT_TYPE);
rect = {CITY_RECT_X0, CITY_RECT_Y0, CITY_RECT_X1, CITY_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s", weather_data->name);
drawtext(tmp_buf, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
/* ==========================今天天气实况====================================== */
/* 今天天气图标 */
sprintf(tmp_buf, "./img/weather_icon/%[email protected]", weather_data->code);
loadimage(&pDstImg, tmp_buf);
putimage(TODAY_WEATHER_ICON_X, TODAY_WEATHER_ICON_Y, &pDstImg, SRCPAINT);
/* 今天天气文字 */
settextstyle(TODAY_TEMPERATURE_FONT_HEIGHT, TODAY_TEMPERATURE_FONT_WIDTH, DEFAULT_FONT_TYPE);
rect = {TODAT_WEATHER_RECT_X0, TODAT_WEATHER_RECT_Y0, TODAT_WEATHER_RECT_X1, TODAT_WEATHER_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s℃ %s", weather_data->temperature, weather_data->text);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
/* ==========================今天、明天、后天天气=============================== */
/* 今天日期 */
settextstyle(DEFAULT_FONT_HEIGHT, DEFAULT_FONT_WIDTH, DEFAULT_FONT_TYPE);
rect = {BOTTOM_TODAY_DATA_RECT_X0, BOTTOM_TODAY_DATA_RECT_Y0, BOTTOM_TODAY_DATA_RECT_X1, BOTTOM_TODAY_DATA_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s", weather_data->date[0]);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
/* 今天天气图标 */
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "./img/weather_icon/%[email protected]", weather_data->code_day[0]);
loadimage(&pDstImg, tmp_buf);
putimage(BOTTOM_TODAY_WEATHER_ICON_X, BOTTOM_TODAY_WEATHER_ICON_Y, &pDstImg, SRCPAINT);
/* 今天气温范围 */
rect = {BOTTOM_TODAY_TEMP_RANGE_RECT_X0, BOTTOM_TODAY_TEMP_RANGE_RECT_Y0, BOTTOM_TODAY_TEMP_RANGE_RECT_X1, BOTTOM_TODAY_TEMP_RANGE_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s℃~%s℃", weather_data->low[0], weather_data->high[0]);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
/* 今天天气文字 */
rect = {BOTTOM_TODAY_WEATHER_RECT_X0, BOTTOM_TODAY_WEATHER_RECT_Y0, BOTTOM_TODAY_WEATHER_RECT_X1, BOTTOM_TODAY_WEATHER_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s", weather_data->text_day[0]);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
/* 明天日期 */
settextstyle(DEFAULT_FONT_HEIGHT, DEFAULT_FONT_WIDTH, DEFAULT_FONT_TYPE);
rect = {BOTTOM_TOMORROW_DATA_RECT_X0, BOTTOM_TOMORROW_DATA_RECT_Y0, BOTTOM_TOMORROW_DATA_RECT_X1, BOTTOM_TOMORROW_DATA_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s", weather_data->date[1]);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
/* 明天天气图标 */
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "./img/weather_icon/%[email protected]", weather_data->code_day[1]);
loadimage(&pDstImg, tmp_buf);
putimage(BOTTOM_TOMORROW_WEATHER_ICON_X, BOTTOM_TOMORROW_WEATHER_ICON_Y, &pDstImg, SRCPAINT);
/* 明天气温范围 */
rect = {BOTTOM_TOMORROW_TEMP_RANGE_RECT_X0, BOTTOM_TOMORROW_TEMP_RANGE_RECT_Y0, BOTTOM_TOMORROW_TEMP_RANGE_RECT_X1, BOTTOM_TOMORROW_TEMP_RANGE_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s℃~%s℃", weather_data->low[1], weather_data->high[1]);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
/* 明天天气文字 */
rect = {BOTTOM_TOMORROW_WEATHER_RECT_X0, BOTTOM_TOMORROW_WEATHER_RECT_Y0, BOTTOM_TOMORROW_WEATHER_RECT_X1, BOTTOM_TOMORROW_WEATHER_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s", weather_data->text_day[1]);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
/* 后天日期 */
settextstyle(DEFAULT_FONT_HEIGHT, DEFAULT_FONT_WIDTH, DEFAULT_FONT_TYPE);
rect = {BOTTOM_AFTER_TOMORROW_DATA_RECT_X0, BOTTOM_AFTER_TOMORROW_DATA_RECT_Y0, BOTTOM_AFTER_TOMORROW_DATA_RECT_X1, BOTTOM_AFTER_TOMORROW_DATA_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s", weather_data->date[2]);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
/* 后天天气图标 */
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "./img/weather_icon/%[email protected]", weather_data->code_day[2]);
loadimage(&pDstImg, tmp_buf);
putimage(BOTTOM_AFTER_TOMORROW_WEATHER_ICON_X, BOTTOM_AFTER_TOMORROW_WEATHER_ICON_Y, &pDstImg, SRCPAINT);
/* 后天气温范围 */
rect = {BOTTOM_AFTER_TOMORROW_TEMP_RANGE_RECT_X0, BOTTOM_AFTER_TOMORROW_TEMP_RANGE_RECT_Y0, BOTTOM_AFTER_TOMORROW_TEMP_RANGE_RECT_X1, BOTTOM_AFTER_TOMORROW_TEMP_RANGE_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s℃~%s℃", weather_data->low[2], weather_data->high[2]);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
/* 后天天气文字 */
rect = {BOTTOM_AFTER_TOMORROW_WEATHER_RECT_X0, BOTTOM_AFTER_TOMORROW_WEATHER_RECT_Y0, BOTTOM_AFTER_TOMORROW_WEATHER_RECT_X1, BOTTOM_AFTER_TOMORROW_WEATHER_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%s", weather_data->text_day[2]);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
}
// 微信公众号:嵌入式大杂烩
struct time_data get_time(void)
{
time_t t;
struct tm *tim;
struct time_data res_time;
const char *wday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
time(&t);
tim = localtime(&t);
res_time.year = 1900 + tim->tm_year;
res_time.mon = 1 + tim->tm_mon;
res_time.mday = tim->tm_mday;
res_time.hour = tim->tm_hour;
res_time.min = tim->tm_min;
res_time.sec = tim->tm_sec;
strncpy(res_time.week, wday[tim->tm_wday], sizeof(wday[tim->tm_wday]));
return res_time;
}
// 微信公众号:嵌入式大杂烩
void time_data_display(struct time_data *tim)
{
RECT rect;
char tmp_buf[50] = {0};
settextstyle(TIME_FONT_HEIGHT, TIME_FONT_WIDTH, DEFAULT_FONT_TYPE);
/* 年月日、星期 */
rect = {DATA_RECT_X0, DATA_RECT_Y0, DATA_RECT_X1, DATA_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%.4d-%.2d-%.2d %s", tim->year, tim->mon, tim->mday, tim->week);
drawtext(tmp_buf, &rect, DT_CENTER | DT_BOTTOM | DT_SINGLELINE);
/* 时分秒 */
rect = {TIME_RECT_X0, TIME_RECT_Y0, TIME_RECT_X1, TIME_RECT_Y1};
memset(tmp_buf, 0, sizeof(tmp_buf));
sprintf(tmp_buf, "%.2d:%.2d:%.2d", tim->hour, tim->min, tim->sec);
drawtext(tmp_buf, &rect, DT_CENTER | DT_SINGLELINE);
}
该代码工程可在本公众号后台回复关键字:基于Easy X的天气预报小程序
,即可获取。如果文章对你有帮助,麻烦帮忙转发,谢谢!
由于微信公众号近期改变了推送规则,如果您想经常看到我们的文章,可以在每次阅读后,在页面下方点一个「赞」或「在看」,这样每次推送的文章才会第一时间出现在您的订阅列表里。
猜你喜欢:
实用 | 分享几个非常实用的开源项目
基于GUILite的简易万年历
STM32如何收发float类型数据?
如何查看Linux命令工具的源码?
2020年精选原创笔记汇总
分享一款嵌入式人必备绘图工具,让你的工作汇报更精彩!(附安装、踩坑、填坑教程)
在公众号聊天界面回复1024,可获取嵌入式资源;回复 m ,可查看文章汇总。