This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository Direct3D.wiki.

View the commit online.

commit 8101ff67c43f6c34c3a6f0a9bb6309398ca34eaf
Author: Vincent Torri <vincent.to...@gmail.com>
AuthorDate: Sat Jul 29 04:42:22 2023 -0700

    Update 'Direct3D 11 for 2D - Creating a window'
---
 Direct3D-11-for-2D---Creating-a-window.md | 578 ++++++++++++++++++++++++++++++
 1 file changed, 578 insertions(+)

diff --git a/Direct3D-11-for-2D---Creating-a-window.md b/Direct3D-11-for-2D---Creating-a-window.md
new file mode 100644
index 0000000..1133186
--- /dev/null
+++ b/Direct3D-11-for-2D---Creating-a-window.md
@@ -0,0 +1,578 @@
+
+# Creating a window
+
+There are numerous tutorials and examples on Internet about creating a window on Windows. So the code is presented below, with some remarks at the end. Here we also use a header file below, `win.h`, which contains structures and interface.
+
+```c
+#ifndef WIN_H
+#define WIN_H
+
+/* comment for no debug informations */
+#define _DEBUG
+
+typedef struct Window Window;
+typedef struct D3d D3d;
+
+struct Window
+{
+    HINSTANCE instance;
+    RECT rect;
+    HWND win;
+    D3d *d3d;
+    int rotation; /* rotation (clockwise): 0, 1, 2 3 */
+    unsigned int fullscreen: 1;
+};
+
+D3d *d3d_init(Window *win, int vsync);
+
+void d3d_shutdown(D3d *d3d);
+
+void d3d_scene_begin(D3d *d3d);
+
+void d3d_scene_end(void);
+
+void d3d_resize(D3d *d3d, int rot, UINT width, UINT height);
+
+void d3d_render(D3d *d3d);
+
+#endif
+```
+
+Here is the corresponding `win.c` file below. The compilation command is at the top of the file.
+
+
+```c
+/*
+ * compilation command (Windows 10 or above):
+ *
+ * gcc -g -O2 -Wall -Wextra -o d3d d3d_0.c win.c -ld3d11 -ld3dcompiler -ldxgi -luuid -D_WIN32_WINNT=0x0A00
+ *
+ * Note: change the d3d_*.c file for each steps of the tutorial
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>
+
+#include "win.h"
+
+void window_fullscreen_set(Window *win, unsigned int fullscreen);
+
+void window_rotation_set(Window *win, int rotation);
+
+/************************* Window *************************/
+
+LRESULT CALLBACK
+_window_procedure(HWND   window,
+                  UINT   message,
+                  WPARAM window_param,
+                  LPARAM data_param)
+{
+    switch (message)
+    {
+        case WM_CLOSE:
+            PostQuitMessage(0);
+            return 0;
+        case WM_KEYUP:
+            if (window_param == 'Q')
+            {
+                PostQuitMessage(0);
+            }
+            if (window_param == 'F')
+            {
+                Window *win;
+
+#ifdef _DEBUG
+                printf("fullscreen\n");
+                fflush(stdout);
+#endif
+                win = (Window *)GetWindowLongPtr(window, GWLP_USERDATA);
+                window_fullscreen_set(win, !win->fullscreen);
+            }
+            if (window_param == 'R')
+            {
+                Window *win;
+
+#ifdef _DEBUG
+                printf("rotation\n");
+                fflush(stdout);
+#endif
+                win = (Window *)GetWindowLongPtr(window, GWLP_USERDATA);
+                window_rotation_set(win, (win->rotation + 1) % 4);
+            }
+            if (window_param == 'D')
+            {
+/*             RECT r; */
+/*             Window* win; */
+
+/* #ifdef _DEBUG */
+/*             printf("draw texture\n"); */
+/*             fflush(stdout); */
+/* #endif */
+/*             win = (Window*)GetWindowLongPtr(window, GWLP_USERDATA); */
+            }
+            if (window_param == 'U')
+            {
+                RECT r;
+                Window* win;
+
+#ifdef _DEBUG
+                printf("update d3d\n");
+                fflush(stdout);
+#endif
+                win = (Window*)GetWindowLongPtr(window, GWLP_USERDATA);
+                GetClientRect(window, &r);
+                d3d_resize(win->d3d,
+                           win->rotation,
+                           r.right - r.left, r.bottom - r.top);
+                d3d_render(win->d3d);
+            }
+            return 0;
+        case WM_ERASEBKGND:
+            /* no need to erase back */
+            return 1;
+            /* GDI notifications */
+        case WM_CREATE:
+#ifdef _DEBUG
+            printf(" * WM_CREATE\n");
+            fflush(stdout);
+#endif
+            return 0;
+        case WM_SIZE:
+        {
+            Window * win;
+
+#ifdef _DEBUG
+            printf(" * WM_SIZE : %u %u\n", (UINT)LOWORD(data_param), (UINT)HIWORD(data_param));
+            fflush(stdout);
+#endif
+
+            win = (Window *)GetWindowLongPtr(window, GWLP_USERDATA);
+            d3d_resize(win->d3d,
+                       win->rotation,
+                       (UINT)LOWORD(data_param), (UINT)HIWORD(data_param));
+
+            return 0;
+        }
+        case WM_PAINT:
+        {
+#ifdef _DEBUG
+            printf(" * WM_PAINT\n");
+            fflush(stdout);
+#endif
+
+            if (GetUpdateRect(window, NULL, FALSE))
+            {
+                PAINTSTRUCT ps;
+                Window *win;
+
+                BeginPaint(window, &ps);
+
+                win = (Window *)GetWindowLongPtr(window, GWLP_USERDATA);
+                d3d_render(win->d3d);
+
+                EndPaint(window, &ps);
+            }
+
+            return 0;
+        }
+        default:
+            return DefWindowProc(window, message, window_param, data_param);
+    }
+}
+
+Window *window_new(int x, int y, int w, int h)
+{
+    WNDCLASS wc;
+    RECT r;
+    Window *win;
+
+    win = (Window *)calloc(1, sizeof(Window));
+    if (!win)
+        return NULL;
+
+    win->instance = GetModuleHandle(NULL);
+    if (!win->instance)
+        goto free_win;
+
+    memset (&wc, 0, sizeof (WNDCLASS));
+    wc.style = CS_HREDRAW | CS_VREDRAW;
+    wc.lpfnWndProc = _window_procedure;
+    wc.cbClsExtra = 0;
+    wc.cbWndExtra = 0;
+    wc.hInstance = win->instance;
+    wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
+    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
+    wc.hbrBackground = NULL;
+    wc.lpszMenuName =  NULL;
+    wc.lpszClassName = "D3D";
+
+    if(!RegisterClass(&wc))
+        goto free_library;
+
+    r.left = 0;
+    r.top = 0;
+    r.right = w;
+    r.bottom = h;
+    if (!AdjustWindowRectEx(&r,
+                            WS_OVERLAPPEDWINDOW | WS_SIZEBOX,
+                            FALSE,
+                            0U))
+        goto unregister_class;
+
+    printf("window new : %d %d %ld %ld", w, h, r.right - r.left, r.bottom - r.top);
+    fflush(stdout);
+
+    win->win = CreateWindowEx(0U,
+                              "D3D", "Direct3D",
+                              WS_OVERLAPPEDWINDOW | WS_SIZEBOX,
+                              x, y,
+                              r.right - r.left,
+                              r.bottom - r.top,
+                              NULL,
+                              NULL, win->instance, NULL);
+    if (!win->win)
+        goto unregister_class;
+
+    return win;
+
+  unregister_class:
+    UnregisterClass("D2D", win->instance);
+  free_library:
+    FreeLibrary(win->instance);
+  free_win:
+    free(win);
+
+    return NULL;
+}
+
+void window_del(Window *win)
+{
+    if (!win)
+        return;
+
+    DestroyWindow(win->win);
+    UnregisterClass("D2D", win->instance);
+    FreeLibrary(win->instance);
+    free(win);
+}
+
+void window_show(Window *win)
+{
+    ShowWindow(win->win, SW_SHOWNORMAL);
+}
+
+void window_fullscreen_set(Window *win, unsigned int on)
+{
+    HWND prev;
+    DWORD style;
+    DWORD exstyle;
+    UINT flags;
+    int x;
+    int y;
+    int w;
+    int h;
+
+    on =  !!on;
+    if ((win->fullscreen && on) ||
+        (!win->fullscreen && !on))
+        return;
+
+    if (on)
+    {
+        MONITORINFO mi;
+        HMONITOR monitor;
+
+        if (!GetWindowRect(win->win, &win->rect))
+        {
+            printf("GetWindowRect() failed\n");
+            return;
+        }
+
+        monitor = MonitorFromWindow(win->win, MONITOR_DEFAULTTONEAREST);
+        mi.cbSize = sizeof(MONITORINFO);
+        if (!GetMonitorInfo(monitor, &mi))
+            return;
+
+        style = WS_VISIBLE | WS_POPUP;
+        exstyle = WS_EX_TOPMOST;
+        prev = HWND_TOPMOST;
+        x = 0;
+        y = 0;
+        w = mi.rcMonitor.right - mi.rcMonitor.left;
+        h = mi.rcMonitor.bottom - mi.rcMonitor.top;
+        flags = SWP_NOCOPYBITS | SWP_SHOWWINDOW;
+    }
+    else
+    {
+
+        style = WS_OVERLAPPEDWINDOW | WS_SIZEBOX;
+        exstyle = 0U;
+        prev = HWND_NOTOPMOST;
+        x = win->rect.left;
+        y = win->rect.top;
+        w = win->rect.right - win->rect.left;
+        h = win->rect.bottom - win->rect.top;
+        flags = SWP_NOCOPYBITS | SWP_SHOWWINDOW;
+    }
+
+    SetLastError(0);
+    if (!SetWindowLongPtr(win->win, GWL_STYLE, style) &&
+        (GetLastError() != 0))
+    {
+        printf("SetWindowLongPtr() failed\n");
+        return;
+    }
+    SetLastError(0);
+    if (!SetWindowLongPtr(win->win, GWL_EXSTYLE, exstyle) &&
+        (GetLastError() != 0))
+    {
+        printf("SetWindowLongPtr() failed\n");
+        return;
+    }
+    if (!SetWindowPos(win->win, prev, x, y, w, h, flags))
+    {
+        printf("SetWindowPos() failed\n");
+        return;
+    }
+
+    win->fullscreen = on;
+}
+
+void window_rotation_set(Window *win, int rotation)
+{
+    int rdiff;
+
+    if (win->rotation == rotation)
+        return;
+
+    rdiff = win->rotation - rotation;
+    if (rdiff < 0) rdiff = -rdiff;
+
+    if (rdiff != 2)
+    {
+        RECT r;
+        RECT r2;
+        int x;
+        int y;
+
+        win->rotation = rotation;
+
+        if (!GetWindowRect(win->win, &r))
+        {
+            printf("GetClient failed\n");
+            return;
+        }
+
+        x = r.left;
+        y = r.top;
+
+        if (!GetClientRect(win->win, &r))
+        {
+            printf("GetClient failed\n");
+            return;
+        }
+
+        printf(" * win rot : %ld %ld\n", r.bottom - r.top, r.right - r.left);
+        fflush(stdout);
+
+        r2.left = 0;
+        r2.top = 0;
+        r2.right = r.bottom - r.top;
+        r2.bottom = r.right - r.left;
+        if (!AdjustWindowRectEx(&r2,
+                                WS_OVERLAPPEDWINDOW | WS_SIZEBOX,
+                                FALSE,
+                                0U))
+        {
+            printf("AdjustWindowRectEx failed\n");
+            return;
+        }
+
+        printf(" * win rot 2 : %ld %ld\n", r2.bottom - r2.top, r2.right - r2.left);
+        fflush(stdout);
+
+        if (!MoveWindow(win->win,
+                        x, y,
+                        r2.right - r2.left, r2.bottom - r2.top,
+                        TRUE))
+        {
+            printf("MoveWindow() failed\n");
+            return;
+        }
+    }
+}
+
+int main()
+{
+    Window *win;
+    D3d *d3d;
+    int ret = 1;
+
+    /* remove scaling on HiDPI */
+    SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
+
+    win = window_new(100, 100, 800, 480);
+    if (!win)
+        return ret;
+
+    d3d = d3d_init(win, 0);
+    if (!d3d)
+    {
+        printf(" * d3d_init() failed\n");
+        fflush(stdout);
+        goto del_window;
+    }
+
+    d3d_scene_begin(d3d);
+
+    ret = 0;
+
+    SetWindowLongPtr(win->win, GWLP_USERDATA, (LONG_PTR)win);
+
+    window_show(win);
+
+    /* mesage loop */
+    while(1)
+    {
+        MSG msg;
+        BOOL ret;
+
+        ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
+        if (ret)
+        {
+            do
+            {
+                if (msg.message == WM_QUIT)
+                    goto beach;
+                TranslateMessage(&msg);
+                DispatchMessageW(&msg);
+            } while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
+        }
+    }
+
+  beach:
+    d3d_scene_end();
+    d3d_shutdown(d3d);
+  del_window:
+    window_del(win);
+
+    return ret;
+}
+```
+
+As you can see, there are some Direct3D function in this code. For now, they are just stub functions. The file is `d3d_0.c`. For each step of the tutorial, the name of the file in the compilation command will need to be changed.
+
+```c
+/*
+ * Tutorial part 0
+ *
+ * Only stub functions, no Direct3D functions yet
+ *
+ * Compilation:
+ *
+ * gcc -g -O2 -Wall -Wextra -o d3d_0 d3d_0.c win.c -ld3d11 -ldxgi -luuid -D_WIN32_WINNT=0x0A00
+ */
+
+#include <stdlib.h> /* calloc() free() */
+#include <stdio.h>  /* printf() fflush() */
+
+#define _DEBUG
+
+/* C API for d3d11 */
+#define COBJMACROS
+
+#include <dxgi1_3.h>     /* DXGI interface */
+#include <d3d11.h>       /* D3D11 interface */
+#include <d3dcompiler.h> /* compilation of shader */
+
+#include "win.h"
+
+#ifdef _DEBUG
+# define FCT \
+do { printf(" * %s\n", __FUNCTION__); fflush(stdout); } while (0)
+#else
+# define FCT \
+do { } while (0)
+#endif
+
+struct D3d
+{
+    unsigned int vsync : 1;
+};
+
+/************************** D3D11 **************************/
+
+D3d *d3d_init(Window *win, int vsync)
+{
+    D3d *d3d;
+
+    d3d = (D3d *)calloc(1, sizeof(D3d));
+    if (!d3d)
+        return NULL;
+
+    return d3d;
+
+    (void)win;
+    (void)vsync;
+}
+
+void d3d_shutdown(D3d *d3d)
+{
+    if (!d3d)
+        return;
+
+    free(d3d);
+}
+
+void d3d_scene_begin(D3d *d3d)
+{
+    (void)d3d;
+}
+
+void d3d_scene_end(void)
+{
+}
+
+void d3d_resize(D3d *d3d, int rot, UINT width, UINT height)
+{
+    (void)d3d;
+    (void)rot;
+    (void)width;
+    (void) height;
+}
+
+void d3d_render(D3d *d3d)
+{
+    (void)d3d;
+}
+```
+
+When the program is launched, you should obtain a window with a white background, like this:
+
+<img alt="tutorial 0" src=""  width="30%" height="30%">
+
+Some actions are implemented:
+
+* Press the key 'q' to quit the program.
+* Press the key 'f' to switch fullscreen / windowed mode
+* Press the key 'r' to rotate clock-wise the window with steps of 90 °. This will be useful when something will be drawn in the window. For now, the only change will be the orientation of the window.
+
+Some remarks:
+
+1. The macro _WIN32_WINNT must be set to 0x0A00 in the compilation command to specify the version 10 of Windows (or above).
+2. The macro _DEBUG will be used for Direct3D only.
+3. The High DPI scaling is removed.
+4. The WM_SIZE message will be used to adapt the size of some of the Direct3D objects, namely:
+ * the viewport,
+ * the swap chain,
+ * the render target view.
+5. The WM_PAINT will be used to render the scene.
+6. There are some optimizations to avoid the redraw of the window background when it is resized:
+ * the WM_ERASEBKGND massage is managed,
+ * the brush of the window class is set to NULL.

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to