直接上代码,glfw_window.hpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#ifndef GLFW_WINDOW_HPP
#define GLFW_WINDOW_HPP
 
#include <cstdlib>                          // onexit()
 
#pragma execution_character_set("utf-8")    // utf8 中文支持
#include <glfw/glfw3.h>
 
 
class glfw_window
{
public:
    GLFWwindow* window;
 
public:
    glfw_window() : window()
    {
         
    }
 
    glfw_window(const char* title, int width, int height) : window()
    {
        this->init(title, width, height);
    }
 
    //
    // 方法
    //
 
    // 创建 glfw 窗口
    int init(const char* title, int width, int height)
    {
        glfw_init();
 
        window = glfwCreateWindow(width, height, title, nullptr, nullptr);
 
        if (!window) {
            // err...
            return -1;
        }
 
        // 设置当前窗口上下文
        glfwMakeContextCurrent(window);
 
        // 设置用户数据,记录当前类指针
        glfwSetWindowUserPointer(window, this);
 
        // 原始 glfw 事件回调函数设置
        glfwSetKeyCallback(window, on_key);
        glfwSetCharCallback(window, on_char);
        glfwSetMouseButtonCallback(window, on_mouse_button);
        glfwSetCursorPosCallback(window, on_cursor_pos);
 
        return 0;
    }
 
    // 释放窗口
    void dispose()
    {
        if (window) {
            // 执行释放事件
            this->on_dispose();
 
            // 销毁窗口
            glfwDestroyWindow(window);
            window = nullptr;
        }
    }
 
    // 执行
    int run()
    {
        // 执行 on_init() 事件。虚函数在构造函数里面不执行,只能放这。
        this->on_init();
 
        while (!glfwWindowShouldClose(window)) {
 
            this->on_draw();            // 绘制函数调用
 
            glfwSwapBuffers(window);    // 反转缓冲区
            glfwPollEvents();           // 窗口事件处理
        }
 
        // 调用释放函数
        this->dispose();
 
        return 0;
    }
 
    // 退出
    void quit()
    {
        if (window) {
            glfwSetWindowShouldClose(window, GLFW_TRUE);
        }
    }
 
    //
    // 属性
    //
 
    // 设置标题
    void set_title(const char* title)
    {
        glfwSetWindowTitle(window, title);
    }
 
    // 设置窗口范围
    void set_bounds(int x, int y, int width, int height)
    {
        glfwSetWindowPos(window, x, y);
        glfwSetWindowSize(window, width, height);
    }
 
    // 窗口左边位置
    int left()const
    {
        int n;
        glfwGetWindowPos(window, &n, NULL);
        return n;
    }
 
    // 窗口右边位置
    int top()const
    {
        int n;
        glfwGetWindowPos(window, NULL, &n);
        return n;
    }
 
    // 窗口宽度
    int width()const
    {
        int n;
        glfwGetWindowSize(window, &n, NULL);
        return n;
    }
 
    // 窗口高度
    int height()const
    {
        int n;
        glfwGetWindowSize(window, NULL, &n);
        return n;
    }
 
    // ... 其他实现
 
    //
    // 事件,通过重载实现调用
    //
 
    virtual void on_init()
    {
 
    }
 
    virtual void on_dispose()
    {
 
    }
 
    virtual void on_keydown(int key)
    {
 
    }
 
    virtual void on_keyup(int key)
    {
 
    }
 
    virtual void on_char(uint32_t ch)
    {
 
    }
 
    // 绘制事件
    virtual void on_draw()
    {
 
    }
 
    // ... 其他实现
 
private:// glfw回调函数
 
    // 获取 glfw 窗口的用户数据,转换成 glfw_window 类指针。
    static glfw_window* get_window(GLFWwindow* window)
    {
        void* userdata = glfwGetWindowUserPointer(window);
        return reinterpret_cast<glfw_window*>(userdata);
    }
 
    //
    // 静态函数,由 glfw 直接调用
    //
 
    static void on_key(GLFWwindow* window, int key, int scancode, int action, int modifier)
    {
        glfw_window* winobj = get_window(window);
 
        switch (action) {
        case GLFW_RELEASE:
            winobj->on_keydown(key);
            break;
        case GLFW_PRESS:
            winobj->on_keyup(key);
            break;
        }
    }
 
    static void on_char(GLFWwindow* window, unsigned int ch)
    {
        glfw_window* winobj = get_window(window);
        winobj->on_char(ch);
    }
 
    // 其他实现...
 
    static void on_mouse_button(GLFWwindow* window, int button, int action, int mods)
    {
 
    }
 
    static void on_cursor_pos(GLFWwindow* window, double xpos, double ypos)
    {
 
    }
 
private:// 自动初始化
    static void glfw_init()
    {
        // 标记是否初始化,这个根据需要调整实现,可以用 singleton。
        static bool init = false;
 
        if (!init) {
            init = true;
 
            glfwInit();
            onexit(glfw_dispose);   // 程序退出时自动执行销毁函数
        }
    }
 
    static int __cdecl glfw_dispose()
    {
        glfwTerminate();
        return 0;
    }
};
 
#endif// GLFW_WINDOW_HPP

  

测试代码,main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "glfw_window.hpp"
 
class MyApp : public glfw_window
{
public:
    MyApp() : glfw_window() {}
 
    MyApp(const char* title, int width, int height) : glfw_window(title, width, height)
    {
    }
 
    void on_init()override
    {
        this->set_title("Yes OpenGL!");
    }
 
    void on_draw()override
    {
        glClearColor(0.0f, 0.5f, 1.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
        //...
    }
 
};
 
 
int main(int argc, char* argv[])
{
    MyApp app = MyApp("OpenGL", 800, 600);
 
    return app.run();
}

  

程序执行结果截图: