Weird window behaviour in Win32 API

The code is given below with build command. Here are some question that you might want me to answer:

  1. What is the intent of this program? This code is in the early stage of writing cross-platform 2D graphics library which, for context of this question, needs to manage multiple windows. Currently I am trying to render an animated window by having platform independent functions and structs in WinMain()

  2. Why do I have an if else statement in WindowProcedure? Its because within the following switch case statements, the function requires WINDOW* to be passed. But for application to handle multiple windows, you need to decide which window sent you to WindowProcedure. But Win32 API only sends you the HWND WindowHandle. So I basically iterate through array of WINDOW structs (WindowArray)and find the matching struct. But when CreateWindow() is called it sends some messages as well, which then calls WindowProcedure before CreateWindow() returns the WindowHandle that I am trying to match with. So I created a global variable LastInitializedIndex to keep track of the window that was just assigned an index in the array and simply use that when CreateWindow() sends its messages.

  3. What is problem with this code? The program compiles properly. When you run it, it displays the window with intended animation with correct size but there is no title bar and border and window stays on top of z-order but you can still click through and interect with other windows.

    When I get rid of Message == WM_NCDESTROY in the WindowProcedure(), window is created unresponsive and then closes automatically, with title bar and border and part of client area is white and rest is black. WM_NCDESTROY is also sent even though documentation doesn’t say so.

  4. Why C like code in C++ program? C is simple enough to think in. Eventually I will add C++ features like constructors, namespaces and all as a part of refactoring. This is my style.

I am compiling using Visual Studio cl.exe and g++ and both give the same results.

console
----
cl -Zi program.cpp user32.lib gdi32.lib && program.exe
console
---
g++ -o program.exe program.cpp -lgdi32 -mwindows && program.exe
program.cpp
-----------

#include <windows.h>
#include <stdint.h>
#include <cstring>

#define WINDOW_MAX_COUNT 256

WNDCLASS WindowClass = {};

typedef struct {
    bool Running;
    uint8_t x;
} STATE;

typedef struct {
    HWND Handle;
    BITMAPINFO Info;

    int Width;
    int Height;
    int XPos;
    int YPos;
    void* Bitmap;
    char* Name;
} WINDOW;

STATE GameState = {};

bool WindowIndecesOccupied[WINDOW_MAX_COUNT] = {};
WINDOW WindowArray[WINDOW_MAX_COUNT] = {};
uint8_t LastInitializedIndex = 0;

void UpdateState(STATE* GameState){
    GameState->x += 1;
}

void UpdateBitmap(STATE* GameState, WINDOW* Window){
    uint32_t* Pixel = (uint32_t*) Window->Bitmap;
    for(int Y = 0; Y < Window->Height; Y++){
        for(int X = 0; X < Window->Width; X++){
            uint8_t Red = 0;
            uint8_t Green = 0;
            uint8_t Blue = GameState->x;

            *Pixel = (Red << 8*2) | (Green << 8*1) | (Blue << 8*0);
            Pixel++;
        }
    }
}

void SetBitmapToWindow(WINDOW* Window){
    HDC DeviceContext = GetDC(Window->Handle);
    SetDIBitsToDevice(DeviceContext, 0, 0, Window->Width, Window->Height, 0, 0, 0, Window->Height, Window->Bitmap, &Window->Info, DIB_RGB_COLORS);
    ReleaseDC(Window->Handle, DeviceContext);
}



WINDOW* InitWindow(int Width, int Height, int XPos, int YPos, char* WindowName){

    WINDOW* Window;
    for(uint8_t Index = 0; Index < WINDOW_MAX_COUNT; Index++){
        if(!WindowIndecesOccupied[Index]){
            WindowIndecesOccupied[Index] = true;
            Window = &WindowArray[Index];
            LastInitializedIndex = Index;
            break;
        }
    }

    Window->Width = Width;
    Window->Height = Height;
    Window->XPos = XPos;
    Window->YPos = YPos;
    Window->Name = WindowName;
    
    Window->Info.bmiHeader.biSize = sizeof(Window->Info.bmiHeader);
    Window->Info.bmiHeader.biWidth = Window->Width;
    Window->Info.bmiHeader.biHeight = -Window->Height;
    Window->Info.bmiHeader.biPlanes = 1;
    Window->Info.bmiHeader.biBitCount = 32;
    Window->Info.bmiHeader.biCompression = BI_RGB;

    Window->Bitmap = VirtualAlloc(0, Window->Width * Window->Height * 4, MEM_COMMIT, PAGE_READWRITE);

    Window->Handle = CreateWindow(WindowClass.lpszClassName, Window->Name, WS_OVERLAPPEDWINDOW, Window->XPos, Window->YPos, Window->Width, Window->Height, 0, 0, WindowClass.hInstance, 0);

    return Window;
}

void UpdateWindowInfo(WINDOW* Window){
    int PrevBitmapSize = Window->Width * Window->Height * 4;
    RECT ClientRect;
    GetClientRect(Window->Handle, &ClientRect);
    Window->Width = ClientRect.right - ClientRect.left;
    Window->Height = ClientRect.bottom - ClientRect.top;
    Window->XPos = ClientRect.left;
    Window->YPos = ClientRect.top;

    Window->Info.bmiHeader.biWidth = Window->Width;
    Window->Info.bmiHeader.biHeight = -Window->Height;
    
    if (PrevBitmapSize != Window->Width * Window->Height * 4){
        if(Window->Bitmap) VirtualFree(Window->Bitmap, 0, MEM_RELEASE);
        Window->Bitmap = VirtualAlloc(0, Window->Width * Window->Height * 4, MEM_COMMIT, PAGE_READWRITE);
    }
}

LRESULT CALLBACK WindowProcedure(HWND WindowHandle, uint32_t Message, WPARAM WParam, LPARAM LParam){
        LRESULT Result = 0;
        WINDOW* Window;

        if(Message == WM_CREATE || Message == WM_GETMINMAXINFO || Message == WM_NCCREATE || Message == WM_NCDESTROY){
            Window = &WindowArray[LastInitializedIndex];
        } else {
            for (uint8_t Index = 0; Index < WINDOW_MAX_COUNT; Index++){
                if(WindowIndecesOccupied[Index] && WindowArray[Index].Handle == WindowHandle){
                    Window = &WindowArray[Index];
                    break;
                }
            }
        }

        switch(Message){
            case WM_MOVE:
            case WM_SIZE:{
                UpdateWindowInfo(Window);
            } break;

            case WM_PAINT:{
                SetBitmapToWindow(Window);
                ValidateRect(Window->Handle, 0);
            } break;

            case WM_DESTROY:
            case WM_CLOSE:
            case WM_QUIT:{
                GameState.Running = false;
                PostQuitMessage(0);
            } break;

            default:{
                Result = DefWindowProc(Window->Handle, Message, WParam, LParam);        
            } break;
        }
    
        return Result;
}

int WinMain(HINSTANCE Instance, HINSTANCE PrevInstance, LPSTR ComandLine, int ShowComand){
    
    WindowClass.lpfnWndProc = WindowProcedure;
    WindowClass.hInstance = Instance;
    WindowClass.lpszClassName = "Espur Window Class";
    
    if(RegisterClass(&WindowClass)){

        WINDOW* Window = InitWindow(800, 800, 0, 0, "Espur Window");

        if (Window->Handle) ShowWindow(Window->Handle, ShowComand);
        GameState.Running = true;
        while(GameState.Running){
            MSG Message = {};
            while(PeekMessage(&Message, 0, 0, 0, PM_REMOVE)){
                TranslateMessage(&Message);
                DispatchMessage(&Message);
            }
            UpdateBitmap(&GameState, Window);
            UpdateState(&GameState);
            SetBitmapToWindow(Window);
        }
    }
}

I want to know why the window is behaving the way it is and any suggestions on how to handle multiple windows at the same time. Or any resources that can help me design the entire library as well.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật