Luciano Machado
Luciano Machado

Reputation: 3

Win32 application still running in background after closing

I am a beginner programmer.

In this code I want to create a window of one color in Win32 API using the C language. I am using the Windows PowerShell and MinGW to compile it. It works, but whenever I try to compile it again after closing it I get this error: …/mingw32/bin/ld.exe: cannot open output file out.exe: Permission denied collect2.exe: error: ld returned 1 exit status

As far as I am concerned, this is a linkage problem and it occurs because Windows cannot make the linkage with the program already being in execution. I do not wish to kill the execution all the time in the Task Manager.

I don't think the code is beyond what Microsoft's documentation tells me to do, I have simply wrapped it in functions and structs instead of writing everything in WinMain, the application loop can be found there. I am creating an RGB array in WM_CREATE and passing it to HBITMAP in WM_PAINT in case you are wondering what I have done, that's why the repeated height and width which I pretend to change later. Here is the code:

#include<windows.h>
#include<stdlib.h>
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Window Procedure
HBITMAP bitmap_handle;
COLORREF *rgb_p=NULL;

LRESULT CALLBACK window_procedure_func(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_CREATE:
        {
            int width=500;
            int height=500;
            rgb_p=(COLORREF*)malloc(width*height*sizeof(COLORREF));
            int  pixel_count=0;
            for(int row=0; row<height; row++)
            {
                for(int col=0; col<width; col++)
                {
                    rgb_p[pixel_count]=RGB(255, 0, 0);
                    pixel_count++;
                }
            }
        }
        break;

        case WM_PAINT:
        {
            int width=500;
            int height=500;
            HBITMAP bitmap_handle=CreateBitmap(width, height, 1, 32, rgb_p);
      
            PAINTSTRUCT     ps;
            HDC             hdc;
            BITMAP          bitmap;
            HDC             hdcMem;
            HGDIOBJ         oldBitmap;

            hdc = BeginPaint(hWnd, &ps);

            hdcMem = CreateCompatibleDC(hdc);
            oldBitmap = SelectObject(hdcMem, bitmap_handle);

            GetObject(bitmap_handle, sizeof(bitmap), &bitmap);
            BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);

            SelectObject(hdcMem, oldBitmap);
            DeleteDC(hdcMem);

            EndPaint(hWnd, &ps);
        }
        break;

        case WM_CLOSE:
        {
            DestroyWindow(hWnd);
        }
        break;

        case WM_DESTROY:
        {
            free(rgb_p);
            DeleteObject(bitmap_handle);
            PostQuitMessage(0);
        }
        break;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Simple functions to initalize a window
struct window_wrapper
{
    WNDCLASS window_class;
    HWND window_handle;
};

WNDCLASS window_class_ini(char *window_name, HINSTANCE instance_handle, WNDPROC window_procedure)
{
    WNDCLASS window_class={};
    window_class.lpfnWndProc=window_procedure;
    window_class.hInstance=instance_handle;
    window_class.lpszClassName=window_name;
    return window_class;
}

HWND window_handle_ini(char *window_name, HINSTANCE instance_handle, int width, int height)
{
    return CreateWindow(
        window_name,
        window_name,
        WS_OVERLAPPEDWINDOW,
        250, 250, width, height,
        NULL,  
        NULL,
        instance_handle,
        NULL);
}

struct window_wrapper *malloc_window_wrapper(char *window_name, HINSTANCE instance_handle, WNDPROC window_procedure, int windows_status, int width, int height)
{
    struct window_wrapper *window_wrapper_p=NULL;
    window_wrapper_p=(struct window_wrapper*)malloc(sizeof(struct window_wrapper));
    window_wrapper_p->window_class=window_class_ini(window_name, instance_handle, window_procedure);
    RegisterClass(&window_wrapper_p->window_class);
    window_wrapper_p->window_handle=window_handle_ini(window_name, instance_handle, width, height);
    ShowWindow(window_wrapper_p->window_handle, windows_status);
    return window_wrapper_p;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Windows Entry Point
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    LRESULT CALLBACK (*procedure_p)(HWND, UINT, WPARAM, LPARAM)=&window_procedure_func;
    struct window_wrapper *wrapper=malloc_window_wrapper("window_name", hInstance, (WNDPROC)procedure_p, nCmdShow, 500, 500);
    MSG msg={};
    int running=1;
    while(running)
    {
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if(msg.message==WM_QUIT)
        {
            running=0;
        }
    }

    free(wrapper);
    return 0;
}

I have tried to use exit() also instead of return 0 at the end but no success. I appreciate the responses.

Upvotes: 0

Views: 1031

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597971

Your message loop is structured incorrectly. Your if statement is reached only when PeekMessage() returns false, meaning the contents of msg are indeterminate. So the if will never see a valid WM_QUIT message (or any valid message, for that matter) to break the loop.

Get rid of the running variable, and use this loop instead:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDPROC procedure_p = &window_procedure_func;
    struct window_wrapper *wrapper = malloc_window_wrapper("window_name", hInstance, procedure_p, nCmdShow, 500, 500);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    free(wrapper);
    return 0;
}

Upvotes: 3

Related Questions