Graphics—对话框操作

终于用OpenGL实现了漫游、粒子系统以及无语的黑盒3D,下面就是头疼的碰撞检测了~要不然偷懒不用OpenGL写了?估计导师会训我啊啊啊啊
累死~~~还是补篇笔记吧,要不然快忘了。

接着上一次的Graphics—菜单设置笔记继续说吧。

其实对话框这东西真的很好玩(^o^)/~
声明:操作方法不一,我只是把做小型绘图系统的经验记录一下。

先立个flag吧(任务要求):三个绘图选择
(1)画国民党党徽
(2)画共青团团徽
(3)画多角星,需要手动输出一个(2 ~ 100)的整数n,表示绘制n角星

源码在这里:

#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
const double PI = acos(-1.0);
struct Color {
    double x, y, z;
    Color(double x = 0, double y = 0, double z = 0)
    : x(x), y(y), z(z) {}
};
struct Point {
    double x, y;
    Point(double x = 0, double y = 0) : x(x), y(y) {}
};
Color c[1000 + 1];
Point p[1000 + 1], p1[1000 + 1], p2[1000 + 1];
void Ring(double r, Color C) {
    glColor3d(C.x, C.y, C.z); glBegin(GL_POLYGON);
    for(int i = 0; i < 10000; i++) {
        double D = 360.0 / 10000 * i / 180 * PI;
        glVertex2d(r * cos(D), r * sin(D));
    }
    glEnd();
}
void Star(double r, int n, Color C, double r0, Color C1, Color C2) {
    //定义n角星凸起的点为顶点,凹下去的点为次顶点
    //画一个n角星,其中r定义顶点到中心的距离,C代表颜色
    //r0代表次顶点到中心的距离
    //若r0不为0则直接使用,反之使用r0 = r * 3 / 8.
    //C1表示顶点到中心是否连线,C2表示次顶点到中心是否连线
    //颜色第一个参数为-1时,说明不连线,反之使用相应颜色连线
    double dis_to_next = 360.0 / n; //顶点间角度
    for(int i = 0; i < n; i++) {
        double D = (dis_to_next * i + 90) / 180 * PI;
        p1[i] = {r * cos(D), r * sin(D)};
    }
    double r_incycle;//次顶点到中心距离
    if(r0 == 0) {
        r_incycle = r * 3 / 8;
    }
    else {
        r_incycle = r0;
    }
    for(int i = 0; i < n; i++) {
        double D = (180 / n + 90 + i * dis_to_next) / 180 * PI;
        p2[i] = {r_incycle * cos(D), r_incycle * sin(D)};
    }
    glColor3d(C.x, C.y, C.z);
    glBegin(GL_POLYGON);//先以次顶点画多边形
    for(int i = 0; i < n; i++) {
        glVertex2d(p2[i].x, p2[i].y);
    }
    glEnd();
    glColor3d(C.x, C.y, C.z);
    for(int i = 0; i < n; i++) {//再逐步涂色
        glBegin(GL_TRIANGLES);
        glVertex2d(p2[i].x, p2[i].y);
        glVertex2d(p1[(i + 1) % n].x, p1[(i + 1) % n].y);
        glVertex2d(p2[(i + 1) % n].x, p2[(i + 1) % n].y);
        glEnd();
    }
    glColor3f(0, 0, 0);  glBegin(GL_LINE_LOOP);
    for(int i = 0; i < n; i++) {//把n角星的边变成黑色
        glVertex2d(p1[i].x, p1[i].y);
        glVertex2d(p2[i].x, p2[i].y);
    }
    glEnd();
    for(int i = 0; i < n; i++) {
        if(C1.x != -1) {//顶点到中心连线
            glColor3d(C1.x, C1.y, C1.z);
            glBegin(GL_LINES);
            glVertex2d(p1[i].x, p1[i].y);
            glVertex2d(0, 0);
            glEnd();
        }
        if(C2.x != -1) {//次顶点到中心连线
            glColor3d(C2.x, C2.y, C2.z);
            glBegin(GL_LINES);
            glVertex2d(p2[i].x, p2[i].y);
            glVertex2d(0, 0);
            glEnd();
        }
    }
}
void myDisplay1(void) {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    Ring(0.5, (Color){0, 0, 1});
    Star(0.5, 14, (Color){1, 1, 1}, 0.3, (Color){-1, 0, 0}, (Color){-1, 0, 0});
    Ring(0.265, (Color){0, 0, 1});
    Ring(0.238, (Color){1, 1, 1});
    glFlush();
}
void myDisplay2(void) {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    Ring(0.55, (Color){1, 1, 0});
    Ring(0.5, (Color){1, 0, 0});
    Star(0.5, 5, (Color){1, 1, 0}, 0.18, (Color){0, 0, 0}, (Color){0, 0, 0});
    glFlush();
}
int n;
void myDisplay3(void) {
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    Ring(0.5, (Color){1, 0, 1});
    Star(0.5, n, (Color){1, 1, 1}, 0, (Color){1, 0, 0}, (Color){0, 0, 0});
    glFlush();
}
int main(int argc, char *argv[]) {
    printf("Welcome!\n\nInstruction:\n\n1, The emblem of the kuomintang\n\n");
    printf("2, The Communist Youth League badge\n\n3, The pattern of the flower\n\n");
    printf("Please choose operator(1~3): ");
    int op; scanf("%d", &op);
    while(op < 1 || op > 3) {
        printf("error!\nPlease choose again: ");
        scanf("%d", &op);
    }
    if(op == 3) {
        printf("Please choose the number of nodes(2~100): ");
        scanf("%d", &n);
        while(n < 2 || n > 100) {
            printf("error!\nPlease choose again: ");
            scanf("%d", &n);
        }
    }
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(600, 600);
    glutCreateWindow("Hello World!");
    if(op == 1) {
        glutDisplayFunc(&myDisplay1);
    }
    else if(op == 2) {
        glutDisplayFunc(&myDisplay2);
    }
    else {
        glutDisplayFunc(&myDisplay3);
    }
    glutMainLoop();
    return 0;
}
一、新建对话框(类)

1098689-20170304212214048-907358808.png

ID修改成一个好记的名字IDD_Choose

1098689-20170304212942798-1605986148.png
1098689-20170304213049470-933181323.png

然后对于这个对话框,新建一个类(类名就为CChooseDialog吧)

1098689-20170304213130016-32065272.png
1098689-20170304213221657-194069339.png

接着,我们来美工一下对话框吧!这里要用到“工具箱”

1098689-20170304213359813-1351404294.png

这里要使用Radio Button,直接拖动放到对话框里面

1098689-20170304213530985-1118299626.png
1098689-20170304213656407-2055274812.png

对每个Button,选择 属性/Caption,修改名字标题名分别为“国民党党徽”、“共青团团徽”、“绘制多角星”。再拖入一个Edit Control(编辑框),用于输入整数n,绘制n角星。

1098689-20170304214129704-1685632597.png

二、分析过程,添加变量和函数

这时候,我们分析一下整个过程:
初始,编辑框不可用。而当我们选择绘制多角星时,它便可以使用,其次在输入数据的时候,要可以判断输入的是否是2~100的整数。

对于编辑框,我们需要添加一个类别为value的CString变量m_data来存储输入的数据以及一个类别为control的变量m_control来控制编辑框是否可用

1098689-20170304214602470-1919736731.png

添加虚函数OnInitDialog()函数,之后初始化对话框使得编辑框处于不可使用状态。

1098689-20170304215218891-547339654.png

BOOL CChooseDialog::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // TODO:  在此添加额外的初始化
    m_control.EnableWindow(false);
    return TRUE;  // return TRUE unless you set the focus to a control
    // 异常:  OCX 属性页应返回 FALSE
}
我们在ChooseDialog.cpp函数里面设置两个变量op,n
int Op, n; // Op 表示1~3 这三种绘图操作,n代表多角星的角数
添加三个Radio Button 对应的BN_CLICKED消息处理函数

1098689-20170304215440157-756830860.png

void CChooseDialog::OnBnClickedRadio1()
{
    // TODO:  在此添加控件通知处理程序代码
    Op = 1;
    m_control.EnableWindow(false); // 编辑框不可用
}


void CChooseDialog::OnBnClickedRadio2()
{
    // TODO:  在此添加控件通知处理程序代码
    Op = 2;
    m_control.EnableWindow(false); // 编辑框不可用
}


void CChooseDialog::OnBnClickedRadio3()
{
    // TODO:  在此添加控件通知处理程序代码
    Op = 3;
    m_control.EnableWindow(true); // 编辑框可用
}
加入“确定按钮“对应的事件函数(注意,要去掉对话框自带的“确定”和“取消”按钮,我们自己拖入两个Button 改好名字即可)

1098689-20170304220216673-972677156.png
1098689-20170304220248610-639755580.png

到这里,我们发现有一个小bug。如果点击了“取消按钮”,那么就表示本次选择无效。于是在ChooseDialog.cpp里面加入一个bool变量start表示本次选择是否有效。
bool start; // 表示本次选择是否有效
void CChooseDialog::OnBnClickedButton1() // 确定按钮
{
    // TODO:  在此添加控件通知处理程序代码
    if (Op == 1 || Op == 2) {
        start = true;
        SendMessage(WM_CLOSE); // 关闭对话框
        return;
    }
    if (Op == 3) {
        UpdateData(true); // 表示获取编辑框的数据
        /*判断输入数据是否满足2~100的整数*/
        bool flag = false;
        int len = m_data.GetLength();
        if (len >= 4) {
            MessageBox(_T("请输入2~100的整数"), _T("提示"));
            return;
        }
        n = 0;
        for (int i = 0; i < len; i++) {
            if (!(m_data[i] - '0' >= 0 && m_data[i] - '0' <= 9)) {
                flag = true; break;
            }
            else {
                n = n * 10 + (m_data[i] - '0');
            }
        }
        if (flag || (!flag && (n <= 1 || n > 100))) {
            MessageBox(_T("请输入2~100的整数"), _T("提示"));
        }
        else {
            start = true;
            SendMessage(WM_CLOSE);
        }
    }
}
void CChooseDialog::OnBnClickedButton2() // 取消按钮
{
    // TODO:  在此添加控件通知处理程序代码
    start = false;
    SendMessage(WM_CLOSE);
}
三、view类的调整
在StudyView.cpp里面加入头文件#include "ChooseDialog.h"
在StudyView.h里面继承ChooseDalog.cpp里面的Op、n、start变量
extern int Op, n;
extern bool start;
在StudyView.h里面加入绘图类,由于在上一篇笔记里面已经加入了Point 和 Color类,这里不再叙述
class Draw_Choose { // 7
public:
    bool init;       // the mark variable of Init function
    bool reshape;    // the mark variable of Reshape function
    bool Mouse;      // the mark variable of Mouse function 
    bool Keyboard;   // the mark variable of Keyboard function
    bool Motion;     // the mark variable of Mouse move fuction
    Draw_Choose(bool a = true, bool b = true, bool c = false, bool d = false, bool e = false) : init(a), reshape(b), Mouse(c), Keyboard(d), Motion(e) {}
    void Init() {
        glClearColor(0.0, 0.0, 0.0, 1.0);
    }
    void Reshape(int cx, int cy) {
        glViewport(0, 0, cx, cy);
        // 设置投影矩阵(透视投影)  
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(60.0, (GLfloat)cx / (GLfloat)cy, 1.0, 1000.0);
        // 设置模型视图矩阵  
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        gluLookAt(0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    };   // 改变窗口大小时对视窗进行的操作
    Color c[1000 + 1];
    Point p[1000 + 1], p1[1000 + 1], p2[1000 + 1];
    void Ring(double r, Color C) {
        glColor3d(C.x, C.y, C.z); glBegin(GL_POLYGON);
        for (int i = 0; i < 10000; i++) {
            double D = 360.0 / 10000 * i / 180 * PI;
            glVertex2d(r * cos(D), r * sin(D));
        }
        glEnd();
    }
    void Star(double r, int n, Color C, double r0, Color C1, Color C2) {
        double dis_to_next = 360.0 / n; //顶点间角度
        for (int i = 0; i < n; i++) {
            double D = (dis_to_next * i + 90) / 180 * PI;
            p1[i] = { r * cos(D), r * sin(D) };
        }
        double r_incycle;//次顶点到中心距离
        if (r0 == 0) {
            r_incycle = r * 3 / 8;
        }
        else {
            r_incycle = r0;
        }
        for (int i = 0; i < n; i++) {
            double D = (180 / n + 90 + i * dis_to_next) / 180 * PI;
            p2[i] = { r_incycle * cos(D), r_incycle * sin(D) };
        }
        glColor3d(C.x, C.y, C.z);
        glBegin(GL_POLYGON);//先以次顶点画多边形
        for (int i = 0; i < n; i++) {
            glVertex2d(p2[i].x, p2[i].y);
        }
        glEnd();
        glColor3d(C.x, C.y, C.z);
        for (int i = 0; i < n; i++) {//再逐步涂色
            glBegin(GL_TRIANGLES);
            glVertex2d(p2[i].x, p2[i].y);
            glVertex2d(p1[(i + 1) % n].x, p1[(i + 1) % n].y);
            glVertex2d(p2[(i + 1) % n].x, p2[(i + 1) % n].y);
            glEnd();
        }
        glColor3f(0, 0, 0);
        glLineWidth(1);
        glBegin(GL_LINE_LOOP);
        for (int i = 0; i < n; i++) {//把n角星的边变成黑色
            glVertex2d(p1[i].x, p1[i].y);
            glVertex2d(p2[i].x, p2[i].y);
        }
        glEnd();
        for (int i = 0; i < n; i++) {
            if (C1.x != -1) {//顶点到中心连线
                glColor3d(C1.x, C1.y, C1.z);
                glLineWidth(1);
                glBegin(GL_LINES);
                glVertex2d(p1[i].x, p1[i].y);
                glVertex2d(0, 0);
                glEnd();
            }
            if (C2.x != -1) {//次顶点到中心连线
                glColor3d(C2.x, C2.y, C2.z);
                glLineWidth(1);
                glBegin(GL_LINES);
                glVertex2d(p2[i].x, p2[i].y);
                glVertex2d(0, 0);
                glEnd();
            }
        }
    }
    void myDisplay1(void) {
        glClear(GL_COLOR_BUFFER_BIT);
        Ring(0.5, Color(0, 0, 1));
        Star(0.5, 14, Color(1, 1, 1), 0.3, Color(-1, 0, 0), Color(-1, 0, 0));
        Ring(0.265, Color(0, 0, 1));
        Ring(0.238, Color(1, 1, 1));
        glFlush();
    }
    void myDisplay2(void) {
        glClear(GL_COLOR_BUFFER_BIT);
        Ring(0.55, Color(1, 1, 0));
        Ring(0.5, Color(1, 0, 0));
        Star(0.5, 5, Color(1, 1, 0), 0.18, Color(0, 0, 0), Color(0, 0, 0));
        glFlush();
    }
    void myDisplay3(void) {
        glClear(GL_COLOR_BUFFER_BIT);
        Ring(0.5, Color(1, 0, 1));
        Star(0.5, n, Color(1, 1, 1), 0, Color(1, 0, 0), Color(0, 0, 0));
        glFlush();
    }
    void Display() {
        if (Op == 1) {
            myDisplay1();
        }
        else if (Op == 2) {
            myDisplay2();
        }
        else {
            myDisplay3();
        }
    }
};
修改StudyView.cpp里面的DrawPicture函数(Case为1是上一笔记里面的菜单,Case 为 1的代码可以忽略掉)
void CStudyView::DrawPicture()
{
    CRect rc; GetWindowRect(&rc);
    int cx = rc.Width(); int cy = rc.Height();
    if (Case == 1) {
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);

        glColor3f(1.0f, 1.0f, 1.0f);
        glRectf(-0.8f, -0.8f, 0.8f, 0.8f);
        Work m_work;
        m_work.Triangle(Color(0, 1, 0), Color(1, 1, 0), Color(1, 0, 0),
            Point(-0.8, 0.8), Point(0.8, 0.8), Point(0, -0.8));

        glBegin(GL_POLYGON);
        glColor3f(1.0f, 0.0f, 1.0f);
        GLfloat r = 0.5;
        for (int i = 1; i <= 1000; i++) {
            glVertex2f(r * cos(PI / 500 * i), r * sin(PI / 500 * i));
        }
        glEnd();

        GLfloat a = 1 / (2 - 2 * cos(72 * PI / 180)); // ???
        GLfloat x = a * cos(18 * PI / 180);
        GLfloat y = a * sin(18 * PI / 180);
        GLfloat z = a * cos(18 * PI / 180);
        glColor3f(0.0f, 0.0f, 1.0f);
        glBegin(GL_LINE_LOOP);
        glVertex2f(0.0f, a); glVertex2f(0.5f, -z);
        glVertex2f(-x, y);   glVertex2f(x, y);
        glVertex2f(-0.5f, -z);
        glEnd();

        m_work.Triangle(Color(1, 0, 0), Color(0, 0, 1), Color(1, 0, 1),
            Point(-0.65, -0.6), Point(-0.6, -0.7), Point(-0.7, -0.7));

        m_work.Triangle(Color(1, 0, 0), Color(1, 0, 1), Color(1, 1, 0),
            Point(0.65, -0.6), Point(0.7, -0.7), Point(0.6, -0.7));
        glFlush();
    }
    else if (Case == 2) {
        Draw_Choose m_work;
        m_work.Init();
        m_work.Reshape(cx, cy);
        m_work.Display();
    }   
}
四、在菜单里面加入一个“对话框绘图”

1098689-20170304223225532-656153052.png

添加事件函数

1098689-20170304223338438-409429295.png

void CStudyView::OnDraw_Choose()
{
    // TODO:  在此添加命令处理程序代码
    CChooseDialog dlg;
    dlg.DoModal();
    if (start) { // 本次选择有效
        Case = 2;
        SendMessage(WM_PAINT); // 绘图
    }
}
五、运行

1098689-20170304230443907-959015266.png

一、选择国民党党徽,点击“确定”:

1098689-20170304230516485-1880544638.png

二、同理共青团团徽:

1098689-20170304230539688-440173101.png

三、多角星:

(1)输入6.5,点击“确定”。提示错误
1098689-20170304230615360-1823417018.png
(2)输入acm,点击“确定”。提示错误
1098689-20170304230748970-1373805498.png
(3)输入6,点击“确定”。成功
1098689-20170304230810095-817778500.png
(4)输入8,点击“取消”。出现的还是上一个6角星
1098689-20170304230919345-1068238589.png

肚子饿死了啊啊啊啊!!!

转载于:https://www.cnblogs.com/Czhenyu/p/6503064.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值