我之前写过一篇文章是介绍easyx图形界面库的,这里我再介绍一位大神写的一个功能强大的计算器,我只把基本计算的功能浓缩过来给大家看看,感兴趣的小伙伴可以去分析下全部的源码
原始地址在这里:
https://codebus.cn/contributor/a/erlingeryi-calc
我们先来看下精简后的效果:
我们接下来通过分解来看下整个计算器的实现过程
第一步:先显示个400*600像素的窗口
显示窗口实现代码:
#include
typedef TCHAR T;
int main()
{
// 创建绘图窗口
initgraph(400, 600);
SetWindowText(GetHWnd(), _T("计算器"));
while (true)
{
Sleep(20);
}
return 0;
}
第二步:在400*600的窗口画出计算器的按钮方格
显示计算器的背景和主题按钮代码:
// 编译环境:Visual C++ 6.0,EasyX 20190314(beta)
// http://www.easyx.cn
//
#include
#define MyChar TCHAR
typedef TCHAR T;
void showscreen();
IMAGE setimage(int wigth, int height, COLORREF rgb);
void copy_img(IMAGE* img1, IMAGE* img2);
void my_putimage(int dstX, int dstY, IMAGE *pimg, int avoid_color, int deviation, double light, int tp, int effect);
bool button[20][20] = { false }; // 屏幕按键标志
int main()
{
// 创建绘图窗口
initgraph(400, 600);
SetWindowText(GetHWnd(), _T("计算器"));
while (true)
{
showscreen();
Sleep(20);
}
return 0;
}
void showscreen()
{
BeginBatchDraw();
IMAGE black = setimage(400, 600, RGB(255, 125, 0)); // 设置绘图,计算器的主背景色R=255,G=125,B=0
my_putimage(0, 0, &black, RGB(255, 255, 255), 0, 1, 30, 0);
black = setimage(100, 50, RGB(0, 0, 0)); // 设置绘图,按钮的颜色为黑色
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 5; j++)
{
if (j >= 1 && j < 4 && i <= 2 || j == 0 && i == 1)
{
if (!button[i][j])
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 90, 0);
else
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 50, 0);
}
else
{
if (!button[i][j])
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 80, 0);
else
{
if (i == 3 && j == 4 || j == 0 && i == 2 || j == 0 && i == 0)
{
IMAGE black = setimage(100, 50, RGB(240, 0, 0)); // 设置绘图
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 50, 0);
}
else if (j == 4 && i == 0 || j == 4 && i == 2 || j <= 4 && j >= 0 && i == 3)
{
IMAGE green = setimage(100, 50, GREEN); // 设置绘图
my_putimage(i * 102, 340 + j * 52, &green, RGB(255, 255, 255), 0, 1, 60, 0);
}
else
{
IMAGE black = setimage(100, 50, RGB(225, 100, 26)); // 设置绘图
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 50, 0);
}
}
}
}
}
EndBatchDraw();
}
IMAGE setimage(int wigth, int height, COLORREF rgb)
{
IMAGE blacks(wigth, height); // 创建 img 对象
SetWorkingImage(&blacks); // 设置绘图目标为 img 对象
setfillcolor(rgb);
solidrectangle(0, 0, wigth, height);
SetWorkingImage(); // 设置绘图目标为绘图窗口
return blacks;
}
// copy img2 to img1
void copy_img(IMAGE* img1, IMAGE* img2)
{
IMAGE* now_working = GetWorkingImage();
Resize(img1, img2->getwidth(), img2->getheight());
SetWorkingImage(img2);
getimage(img1, 0, 0, img1->getwidth(), img1->getheight());
SetWorkingImage(now_working);
}
void my_putimage(int dstX, int dstY, IMAGE *pimg, int avoid_color, int deviation, double light, int tp, int effect)
{
int x, y, num;
int R, G, B; // 记录贴图某点色彩
// 记录排除颜色色彩
int avoid_r = GetRValue(avoid_color);
int avoid_g = GetGValue(avoid_color);
int avoid_b = GetBValue(avoid_color);
IMAGE pSrcImg; // 背景图
IMAGE tempimg; // 临时贴图
copy_img(&tempimg, pimg);
SetWorkingImage(NULL); // 对默认绘图窗口的绘图操作
getimage(&pSrcImg, dstX, dstY, pimg->getwidth(), pimg->getheight());
// 透明度容错
if (tp < 0)tp = 0;
else if (tp > 100)tp = 100;
// 获取背景指向显存的指针
DWORD* bk_pMem = GetImageBuffer(&pSrcImg);
// 贴图指向显存的指针
DWORD* pMem = GetImageBuffer(&tempimg);
for (y = 0; y < pimg->getheight(); y++)
{
for (x = 0; x < pimg->getwidth(); x++)
{
num = y * pimg->getwidth() + x;
R = GetRValue(pMem[num]);
G = GetGValue(pMem[num]);
B = GetBValue(pMem[num]);
if ((abs(R - avoid_r) <= deviation) && (abs(G - avoid_g) <= deviation) && (abs(B - avoid_b) <= deviation))
{
pMem[num] = bk_pMem[num];
}
else
{
if (light > 0 && light < 1)
{
R = int(R * light);
G = int(G * light);
B = int(B * light);
}
else if (light > 1)
{
R = min(int(R * light), 255);
G = min(int(G * light), 255);
B = min(int(B * light), 255);
}
if (effect == 1)//反相
{
pMem[num] = 0xffffff - pMem[num];
continue;
}
else if (effect == 2)//黑白
{
R = G = B = int(R * 0.299 + G * 0.587 + B * 0.114);
}
pMem[num] = RGB((R * tp + GetRValue(bk_pMem[num]) * (100 - tp)) / 100,
(G * tp + GetGValue(bk_pMem[num]) * (100 - tp)) / 100,
(B * tp + GetBValue(bk_pMem[num]) * (100 - tp)) / 100);
}
}
}
putimage(dstX, dstY, &tempimg);
}
第三步:显示按钮上的字符,看起来是不是有点计算器的样子了
void showscreen()
{
BeginBatchDraw();
IMAGE black = setimage(400, 600, RGB(255, 125, 0)); // 设置绘图,计算器的主背景色R=255,G=125,B=0
my_putimage(0, 0, &black, RGB(255, 255, 255), 0, 1, 30, 0);
black = setimage(100, 50, RGB(0, 0, 0)); // 设置绘图,按钮的颜色为黑色
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 5; j++)
{
if (j >= 1 && j < 4 && i <= 2 || j == 0 && i == 1)
{
if (!button[i][j])
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 90, 0);
else
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 50, 0);
}
else
{
if (!button[i][j])
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 80, 0);
else
{
if (i == 3 && j == 4 || j == 0 && i == 2 || j == 0 && i == 0)
{
IMAGE black = setimage(100, 50, RGB(240, 0, 0)); // 设置绘图
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 50, 0);
}
else if (j == 4 && i == 0 || j == 4 && i == 2 || j <= 4 && j >= 0 && i == 3)
{
IMAGE green = setimage(100, 50, GREEN); // 设置绘图
my_putimage(i * 102, 340 + j * 52, &green, RGB(255, 255, 255), 0, 1, 60, 0);
}
else
{
IMAGE black = setimage(100, 50, RGB(225, 100, 26)); // 设置绘图
my_putimage(i * 102, 340 + j * 52, &black, RGB(255, 255, 255), 0, 1, 50, 0);
}
}
}
}
}
// 添加的按钮字符
settextstyle(30, 0, _T("微软雅黑"), 0, 0, 900, 0, 0, 0);
settextcolor(RGB(255, 255, 255));
setbkmode(TRANSPARENT);
settextstyle(23, 0, _T("Consolas"));
outtextxy(223, 355, _T("delete"));
settextstyle(30, 0, _T("Consolas"));
outtextxy(40, 350, 'C');
outtextxy(142, 560, '.');
outtextxy(142, 350, '0');
outtextxy(36, 560, '(');
outtextxy(40, 508, '1');
outtextxy(142, 508, '2');
outtextxy(244, 508, '3');
outtextxy(40, 456, '4');
outtextxy(142, 456, '5');
outtextxy(244, 456, '6');
outtextxy(40, 404, '7');
outtextxy(142, 404, '8');
outtextxy(244, 404, '9');
outtextxy(248, 560, ')');
settextstyle(40, 0, _T("Consolas"));
outtextxy(342, 500, '+');
outtextxy(342, 344, _T("÷"));
outtextxy(342, 396, _T("×"));
outtextxy(342, 552, '=');
settextstyle(40, 25, _T("Consolas"));
outtextxy(339, 448, '-');
EndBatchDraw();
}
总结:
计算器的外形构造先介绍到这里,我们看到整个外形构造实现起来还是不复杂,当然这个前提是easyx提供了方便的画图用的库,我们采用画图的方式将整个计算器的雏形绘制出来,后面我们再继续介绍计算器的计算核心的实现。