You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In order to create a window, we're going to be using platform specific code. Please note that this tutorial is for Windows **only**. None of this will apply to Linux, Android, GLFW, etc.
3
+
In order to create a window, we're going to be using platform specific code. Please note that this tutorial is for Windows **only**. None of this will apply to Linux, Android, GLFW, etc. I'll make the warning ahead of time: this chapter makes use of a lot of functions. Their definitions are not super relevant to you as a Vulkan developer because this will be written once.
4
4
5
5
### Including Headers
6
6
@@ -14,75 +14,102 @@ If you're targeting Linux as well, you should surround both by the `#if defined(
14
14
15
15
### Setting Up a Console Window
16
16
17
-
Because we're now switching from a **Windows Console Application** to a **Windows Application**, we'll need to make sure we have a console to view the output of `stdout` and `stderr`. In addition, because we're exiting right after we encounter an error, we should:
17
+
Because we're now switching from a **Windows Console Application** to a **Windows Application**, we'll need to make sure we have a console to view the output of `stdout` and `stderr`. Also, because we're exiting right after we encounter an error, we should:
18
18
19
19
- Show a message box
20
20
- Wait for user input (keypress)
21
21
- Close after the user has acknowledged the error
22
22
23
-
We'll be using four methods to do this work:
23
+
We'll be using four methods to do this work.
24
+
25
+
**Definition for `AllocConsole`**:
24
26
25
27
```cpp
26
28
BOOL WINAPI AllocConsole(void);
27
29
```
28
30
29
-
- [Documentation](https://goo.gl/8k36tq)
31
+
**[Documentation](https://goo.gl/8k36tq) for `AllocConsole`**:
32
+
30
33
- This function takes no arguments
31
34
35
+
**Usage for `AllocConsole`**:
36
+
37
+
```cpp
38
+
AllocConsole();
39
+
```
40
+
41
+
**Definition for `AttachConsole`**:
42
+
32
43
```cpp
33
44
BOOL WINAPI AttachConsole(
34
45
_In_ DWORD dwProcessId
35
46
);
36
47
```
37
48
38
-
-[Documentation](https://goo.gl/EeSrhh)
49
+
**[Documentation](https://goo.gl/EeSrhh) for `AttachConsole`**:
50
+
39
51
-`dwProcessId` is the identifier of the process whose console is to be used.
**[Documentation](http://www.cplusplus.com/reference/cstdio/freopen/) for `freopen`**:
69
+
49
70
-`fileName` is a C string containing the name of the file to be opened.
50
71
-`mode` is a C string containing a file access mode. It can be:
51
72
-`"r"`
52
73
-`"w"`
53
74
-`"a"`
54
-
- `"r+"`
55
-
- `"w+"`
56
-
- `"a+"`
75
+
- etc.
57
76
-`stream` is a pointer to a `FILE` object that identifies the stream to be reopened.
58
77
78
+
**Usage for `freopen`**:
79
+
80
+
```cpp
81
+
freopen("CON", "w", stdout);
82
+
freopen("CON", "w", stderr);
83
+
```
84
+
85
+
**Definition for `SetConsoleTitle`**:
86
+
59
87
```cpp
60
88
BOOL WINAPI SetConsoleTitle(
61
89
_In_ LPCTSTR lpConsoleTitle
62
90
);
63
91
```
64
92
65
-
-[Documentation](https://goo.gl/HAIfMd)
93
+
**[Documentation](https://goo.gl/HAIfMd) for `SetConsoleTitle`**:
94
+
66
95
-`lpConsoleTitle` is the string to be displayed in the title bar of the console window. The total size must be less than 64K.
67
96
97
+
**Usage for `SetConsoleTitle`**:
98
+
99
+
```cpp
100
+
SetConsoleTitle(TEXT(applicationName));
101
+
```
102
+
68
103
If you put these methods together you can:
69
104
70
105
- Allocate a console
71
106
- Attach the console to the current process
72
107
- Redirect `stdout` and `stderr` to said console
73
108
- Set the title of the console window
74
109
75
-
Let's look at the code:
110
+
Now, let's modify our `exitOnError` method to show a error message box. We'll need to use the `MessageBox` method.
76
111
77
-
```cpp
78
-
AllocConsole();
79
-
AttachConsole(GetCurrentProcessId());
80
-
freopen("CON", "w", stdout);
81
-
freopen("CON", "w", stderr);
82
-
SetConsoleTitle(TEXT(applicationName));
83
-
```
84
-
85
-
Now, let's modify our `exitOnError` method to show a error message box. We'll need to use the `MessageBox` method:
112
+
**Definition for `MessageBox`**:
86
113
87
114
```cpp
88
115
int WINAPI MessageBox(
@@ -93,12 +120,15 @@ int WINAPI MessageBox(
93
120
);
94
121
```
95
122
96
-
-[Documentation](https://goo.gl/7tAVnv)
123
+
**[Documentation](https://goo.gl/7tAVnv) for `MessageBox`**:
124
+
97
125
-`hWnd` is a handle to the owner window of the message box to be created. If this parameter is `NULL`, the message box has no owner window.
98
126
-`lpText` is the message to be displayed. If the string consists of more than one line, you can separate the lines using a carriage return and/or linefeed character between each line.
99
127
-`lpCaption` is the dialog box title. If this parameter is `NULL`, the default title is "Error".
100
128
-`uType` is the contents and behavior of the dialog box. This parameter can be a combination of flags.
@@ -121,18 +151,9 @@ In this section we'll be writing the body this method:
121
151
voidcreateWindow(HINSTANCE hInstance) {}
122
152
```
123
153
124
-
Don't worry about `hInstance` for now. It is simply passed from the `WinMain` method we'll write later on. To setup our window, we'll need to register it with Windows. You can find the documentation for the `RegisterClassEx` method [here](https://goo.gl/m3WViB). The definition looks like this:
125
-
126
-
```cpp
127
-
ATOM WINAPI RegisterClassEx(
128
-
_In_ const WNDCLASSEX *lpwcx
129
-
);
130
-
```
131
-
132
-
As you see, we'll need to call it with a `WNDCLASSEX` object. You can find the documentation [here](https://goo.gl/1M92FX). The definition and valid usage look like this:
154
+
Don't worry about `hInstance` for now. It is passed from the `WinMain` method we'll write later on. To setup our window, we'll need to register it with Windows, but first, we need to create a `WNDCLASSEX` object to pass during registration.
133
155
134
156
```cpp
135
-
// Definition
136
157
typedef struct WNDCLASSEX {
137
158
UINT cbSize;
138
159
UINT style;
@@ -147,8 +168,26 @@ typedef struct WNDCLASSEX {
147
168
LPCTSTR lpszClassName;
148
169
HICON hIconSm;
149
170
} WNDCLASSEX, *PWNDCLASSEX;
171
+
```
172
+
173
+
**[Documentation](https://goo.gl/1M92FX) for `WNDCLASSEX`**:
150
174
151
-
// Usage
175
+
-`cbSize` is the size, in bytes, of this structure. Set this member to `sizeof(WNDCLASSEX)`. Be sure to set this member before calling the `GetClassInfoEx` function.
176
+
-`style` is the class style(s). This member can be any combination of the Class Styles.
177
+
-`lpfnWndProc` is a pointer to the window procedure. You must use the `CallWindowProc` function to call the window procedure.
178
+
-`cbClsExtra` is the number of extra bytes to allocate following the window-class structure.
179
+
-`cbWndExtra` is the number of extra bytes to allocate following the window instance.
180
+
-`hInstance` is a handle to the instance that contains the window procedure for the class.
181
+
-`hIcon` is a handle to the class icon. This member must be a handle to an icon resource. If this member is `NULL`, the system provides a default icon.
182
+
-`hCursor` is a handle to the class cursor.
183
+
-`hbrBackground` A handle to the class background brush.
184
+
-`lpszMenuName` is a pointer to a null-terminated character string that specifies the resource name of the class menu, as the name appears in the resource file. If you use an integer to identify the menu, use the `MAKEINTRESOURCE` macro.
185
+
-`lpszClassName` is a pointer to a null-terminated string or is an atom.
186
+
-`hIconSm` is a handle to a small icon that is associated with the window class.
As I said, I'm not going to go too much into detail on what each field means so we'll move on to registering the window. Calling `RegisterClassEx` returns `NULL` upon failure so we should make sure we check for that.
207
+
Now, we can make a call to `RegisterClassEx` to get Windowss to register the Window class.
208
+
209
+
**Definition for `RegisterClassEx`**:
169
210
170
211
```cpp
171
-
if (!RegisterClassEx(&wcex))
212
+
ATOM WINAPI RegisterClassEx(
213
+
_In_ const WNDCLASSEX *lpwcx
214
+
);
215
+
```
216
+
217
+
**[Documentation](https://goo.gl/m3WViB) for `RegisterClassEx`**:
218
+
219
+
-`lpwcx` is a pointer to a `WNDCLASSEX` structure. You must fill the structure with the appropriate class attributes before passing it to the function.
220
+
221
+
**Usage for `RegisterClassEx`**:
222
+
223
+
Calling `RegisterClassEx` returns `NULL` upon failure so we should make sure we check for that.
int windowTop = screenHeight / 2 - windowHeight / 2;
199
254
```
200
255
201
-
Finally, we can call Window's `CreateWindow` method. You can find documentation [here](https://goo.gl/dmHFfS). The definition and valid usage look like this:
256
+
Finally, we can call Window's `CreateWindow` method. This will, as the name suggests, create the window like we want. We'll specify dimensions, location, and other parameters.
257
+
258
+
**Definition for `CreateWindow`**:
202
259
203
260
```cpp
204
-
// Definition
205
261
HWND WINAPI CreateWindow(
206
262
_In_opt_ LPCTSTR lpClassName,
207
263
_In_opt_ LPCTSTR lpWindowName,
@@ -215,8 +271,25 @@ HWND WINAPI CreateWindow(
215
271
_In_opt_ HINSTANCE hInstance,
216
272
_In_opt_ LPVOID lpParam
217
273
);
274
+
```
275
+
276
+
**[Documentation](https://goo.gl/dmHFfS) for `CreateWindow`**:
277
+
278
+
-`lpClassName` is a null-terminated string or a class atom created by a previous call to the `RegisterClass` or `RegisterClassEx` function. The atom must be in the low-order word of `lpClassName`; the high-order word must be zero. If `lpClassName` is a string, it specifies the window class name.
279
+
-`lpWindowName` is the window name. If the window style specifies a title bar, the window title pointed to by lpWindowName is displayed in the title bar.
280
+
-`dwStyle` is the style of the window being created. This parameter can be a combination of the window style values.
281
+
-`x` is the initial horizontal position of the window.
282
+
-`y` is the initial vertical position of the window.
283
+
-`nWidth` is the width, in device units, of the window.
284
+
-`nHeight` is the height, in device units, of the window.
285
+
-`hWndParent` is a handle to the parent or owner window of the window being created or `NULL` in our case.
286
+
-`hMenu` is a handle to a menu, or specifies a child-window identifier depending on the window style or `NULL` in our case.
287
+
-`hInstance` is a handle to the instance of the module to be associated with the window.
288
+
-`lpParam` is a pointer to a value to be passed to the window through the `CREATESTRUCT` structure (`lpCreateParams` member) pointed to by the `lParam` param of the `WM_CREATE` message or `NULL` in our case.
218
289
219
-
// Usage
290
+
**Usage for `CreateWindow`**:
291
+
292
+
```
220
293
window = CreateWindow(
221
294
applicationName,
222
295
applicationName,
@@ -234,10 +307,11 @@ window = CreateWindow(
234
307
The `CreateWindow` method also returns `NULL` upon failure. Let's deal with that possibility before we move on:
235
308
236
309
```cpp
237
-
if (!window) exitOnError("Failed to create window");
310
+
if (!window)
311
+
exitOnError("Failed to create window");
238
312
```
239
313
240
-
Last, but not least, we should show the window, set it in the foreground, and focus it. Windows provides three methods that do exactly that:
314
+
Last, but not least, we should show the window, set it in the foreground, and focus it. Windows provides three methods that do exactly that. These are very self explanatory:
241
315
242
316
```cpp
243
317
ShowWindow(window, SW_SHOW);
@@ -253,7 +327,7 @@ For this section, we'll be writing the body of this method:
We need to destroy the window and tell Windows we quit if the user attempted to close the window. If we're told we need to paint, we'll simply update the window. If neither of those cases we're met, we'll simply call the window's default procedure to handle events we didn't process. You can do this like so:
330
+
We need to destroy the window and tell Windows we quit if the user attempted to close the window. If we're told we need to paint, we'll simply update the window. If neither of those cases we're met, we'll the default procedure to handle events we didn't process. You can do this like so:
257
331
258
332
```cpp
259
333
switch (message) {
@@ -278,7 +352,13 @@ For this section, we'll write the body of this method:
278
352
voidVulkanExample::renderLoop() {}
279
353
```
280
354
281
-
We're calling it `renderLoop` because later we'll make calls to rendering functions within it. For now, however, we're going to create a message, loop while we have Windows set it, Windows translate it into a character message then add it to the thread queue, and dispatch the message to the windows procedure. While that sounds complicated, it can be done with just a few lines of code:
355
+
We're calling it `renderLoop` because later we'll make calls to rendering functions within it. For now, however, we're going to:
356
+
357
+
- Create a message, loop while we have Windows set it
358
+
- Windows translate it into a character message then add it to the thread queue
359
+
- Dispatch the message to the windows procedure.
360
+
361
+
While that sounds complicated, it can be done with just a few lines of code:
282
362
283
363
```cpp
284
364
MSG message;
@@ -297,18 +377,27 @@ This is our application's new entry-point. We will **not** be using your typical
297
377
- Call our `initWindow` method
298
378
- Call our `renderLoop`
299
379
300
-
You can find documentation on the `WinMain` entry-point [here](https://goo.gl/uToSOo). The definition and our usage are:
380
+
**Definition for `WinMain`**:
301
381
302
382
```cpp
303
-
// Definition
304
383
int CALLBACK WinMain(
305
384
_In_ HINSTANCE hInstance,
306
385
_In_ HINSTANCE hPrevInstance,
307
386
_In_ LPSTR lpCmdLine,
308
387
_In_ int nCmdShow
309
388
);
389
+
```
310
390
311
-
// Our implementation
391
+
**[Documentation](https://goo.gl/uToSOo) for `WinMain`**:
392
+
393
+
-`hInstance` is a handle to the current instance of the application.
394
+
-`hPrevInstance` is a handle to the previous instance of the application. This parameter is always `NULL`.
395
+
-`lpCmdLine` is the command line for the application, excluding the program name.
396
+
-`nCmdShow` controls how the window is to be shown.
397
+
398
+
**Usage for `WinMain`**:
399
+
400
+
```cpp
312
401
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
0 commit comments