Handmade Hero»Forums»Code
chodish
3 posts
Problem with rendering window
I'm working through the code and have made it to video 5 and am having some issues. After altering the code from bitblit to StretchDIBits I now have a blank white screen when I run the .exe file. With Bitblit I was able to see color in the window. I have followed videos through number 6 and my controller vibrates when I open the window but still the screen is white. When I minimize it the window open back up black, and if I resize it with minimizing first the white is replaced with black as the window is repainted in the dirty areas. Any help or suggestions anyone could provide would be appreciated. I have looked over the code and I'm fairly sure its exactly the same, and when I debug it I get the same results as Casey. All my variables are set, pointers have addresses etc. etc. I feel I've reached the end of my abilities to solve this problem and I'd appreciate any help you could provide. Thanks in advance.
Mārtiņš Možeiko
2559 posts / 2 projects
Problem with rendering window
Edited by Mārtiņš Možeiko on
Do you mind showing the code? It's hard to tell what could be wrong without seeing the code.
chodish
3 posts
Problem with rendering window
This is the whole file, I'm not sure what all functions are applicable.


#include <stdint.h>
#include <windows.h>
#include <xinput.h>
#define local_persist

#define global_variable static
#define internal static

typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;

typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
struct win32_offscreen_buffer
{
BITMAPINFO Info;
void *Memory;
int Width;
int Height;
int Pitch;
int BytesPerPixel;
};

global_variable bool GlobalRunning;//this is global for now
global_variable win32_offscreen_buffer GlobalBackbuffer;

struct win32_window_dimension
{
int Width;
int Height;
};

#define X_INPUT_GET_STATE(name)DWORD WINAPI name(DWORD dwUserIndex,XINPUT_STATE *pstate)
typedef X_INPUT_GET_STATE (x_input_get_state);

#define XInputGetState XInputGetState_

X_INPUT_GET_STATE(xInputGetStateStub)
{
return(0);
}
global_variable x_input_get_state *XInputGetState_ = xInputGetStateStub;
#define X_INPUT_SET_STATE(name)DWORD WINAPI name(DWORD dwUserIndex,XINPUT_VIBRATION *pVibration)
typedef X_INPUT_SET_STATE (x_input_set_state);

#define XInputSetState XInputSetState_

X_INPUT_SET_STATE(xInputSetStateStub)
{
return(0);
}
global_variable x_input_set_state *XInputSetState_ = xInputSetStateStub ;

//typedef DWORD WINAPI x_input_get_state(DWORD dwUserIndex,XINPUT_STATE *pState);
//typedef DWORD WINAPI x_input_set_state(DWORD dwUserIndex,XINPUT_VIBRATION* pVibration);




internal void
Win32LoadXInput(void)
{
HMODULE XInputLibrary = LoadLibrary("xinput1_3.dll");
if(XInputLibrary)
{
XInputGetState = (x_input_get_state *)GetProcAddress(XInputLibrary,"XInputGetState" );
XInputSetState = (x_input_set_state *)GetProcAddress(XInputLibrary,"XInputSetState" );
}

}


internal win32_window_dimension
Win32GetWindowDimension(HWND Window)
{
win32_window_dimension Result;
RECT ClientRect;
GetClientRect(Window,&ClientRect);
Result.Width= ClientRect.right=ClientRect.left;
Result.Height= ClientRect.bottom-ClientRect.top;
return(Result);

}
internal void
RenderWeirdGradient(win32_offscreen_buffer *Buffer ,int BlueOffset,int GreenOffset)
{
int Width = Buffer->Width;
int Height= Buffer->Height;


uint8 *Row = (uint8*)Buffer->Memory;
for(int y = 0;
y < Buffer->Height;
++y)
{
uint32 *Pixel = (uint32 *)Row;
for (int x = 0;
x < Buffer->Width;
++x)
{
int8 Blue=(x+BlueOffset);
int8 Green=(y+GreenOffset);

*Pixel++ = ((Green << 8)|Blue);

}



Row += Buffer->Pitch;
}
}


internal void
Win32ResizeDIBSection(win32_offscreen_buffer *Buffer,int Width, int Height)
{
//Maybe don't free first
if(Buffer->Memory)
{
VirtualFree(Buffer->Memory,0,MEM_RELEASE);
}
Buffer->Width = Width;
Buffer->Height = Height;
Buffer->BytesPerPixel = 4;
Buffer->Info.bmiHeader.biSize = sizeof(Buffer->Info.bmiHeader);
Buffer->Info.bmiHeader.biWidth = Buffer->Width;
Buffer->Info.bmiHeader.biHeight = -Buffer->Height;
Buffer->Info.bmiHeader.biPlanes = 1;
Buffer->Info.bmiHeader.biBitCount = 32;
Buffer->Info.bmiHeader.biCompression = BI_RGB;

int BitmapMemorySize =(Buffer->Width*Buffer->Height)*Buffer->BytesPerPixel;
Buffer->Memory = VirtualAlloc(0,BitmapMemorySize,MEM_COMMIT,PAGE_READWRITE);
Buffer->Pitch = Width*Buffer->BytesPerPixel;
}

internal void
Win32DisplayBufferInWindow(HDC DeviceContext,int WindowWidth,int WindowHeight
,win32_offscreen_buffer Buffer)
{
// int WindowWidth = ClientRect.right - ClientRect.left;
//int WindowHeight = ClientRect.bottom - ClientRect.top;
StretchDIBits(DeviceContext,

/*
x,y,Width,Height,
x,y,Width,Height,
*/

0,0,WindowWidth,WindowHeight,
0,0,Buffer.Width,Buffer.Height,
Buffer.Memory,
&Buffer.Info,
DIB_RGB_COLORS, SRCCOPY);



}

LRESULT CALLBACK

Win32MainWindowCallback(
HWND Window,
UINT Message,
WPARAM WParam,
LPARAM LParam)
{
LRESULT Result=0;
switch(Message)
{
case WM_SIZE:
{

}
break;

case WM_CLOSE://give user prompt before close?
{
GlobalRunning=false;

}
break;
case WM_ACTIVATEAPP:
{
OutputDebugStringA("ACTIVATE_APP");
}
break;
case WM_DESTROY://handle this maybe recreate window
{
GlobalRunning=false;
}
break;

case WM_PAINT:
{
PAINTSTRUCT Paint;
HDC DeviceContext=BeginPaint(Window,&Paint);
int x= Paint.rcPaint.left;
int y= Paint.rcPaint.right;
int Width= Paint.rcPaint.right=Paint.rcPaint.left;
int Height= Paint.rcPaint.bottom-Paint.rcPaint.top;
win32_window_dimension Dimension = Win32GetWindowDimension(Window);
//Win32UpdateWindow(DeviceContext,ClientRect, x,y,Width,Height);
Win32DisplayBufferInWindow(DeviceContext,Dimension.Width,Dimension.Height,
GlobalBackbuffer);

EndPaint(Window,&Paint);


}
break;
default:
{
Result=DefWindowProc(Window,Message,WParam,LParam);
}
break;
}
return(Result);
}
int CALLBACK
WinMain(HINSTANCE Instance,
HINSTANCE PrevInstance,
LPSTR CommandLine,
int ShowCode)

{
WNDCLASS WindowClass={};
Win32LoadXInput();
Win32ResizeDIBSection(&GlobalBackbuffer,1280,720);


WindowClass.style=CS_HREDRAW|CS_VREDRAW;
WindowClass.lpfnWndProc=Win32MainWindowCallback;
//int cbWndExtra;
WindowClass.hInstance=Instance;
//HICON hIcon;
//HCURSOR hCursor;
//HBRUSH hbrBackground;
//LPCTSTR lpszMenuName;
WindowClass.lpszClassName = "SpaceCaravanWindowClass";
//WNDCLASS, *PWNDCLASCS_HREDRAWS;

if( RegisterClass(&WindowClass))
{
HWND Window=CreateWindowExA(
0,
WindowClass.lpszClassName,
"Space Caravan",
WS_OVERLAPPEDWINDOW|WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,

CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
Instance,
0);
if(Window)
{
HDC DeviceContext = GetDC(Window);
int XOffset=0;
int YOffset=0;

GlobalRunning=true;
while(GlobalRunning)
{
MSG Message;



while(PeekMessage(&Message,0,0,0,PM_REMOVE))
{
if(Message.message == WM_QUIT)
{
GlobalRunning = false;
}

TranslateMessage(&Message);
DispatchMessage(&Message);
}
for (DWORD ControllerIndex=0;
ControllerIndex< XUSER_MAX_COUNT;
++ControllerIndex )

{
XINPUT_STATE ControllerState;
if(XInputGetState(ControllerIndex,&ControllerState)== ERROR_SUCCESS)
{

XINPUT_GAMEPAD *Pad = &ControllerState.Gamepad;
bool Up = (Pad->wButtons & XINPUT_GAMEPAD_DPAD_UP);
bool Down = (Pad->wButtons & XINPUT_GAMEPAD_DPAD_DOWN);
bool Left = (Pad->wButtons & XINPUT_GAMEPAD_DPAD_LEFT);
bool Right = (Pad->wButtons &XINPUT_GAMEPAD_DPAD_RIGHT);
bool Start = ( Pad->wButtons &XINPUT_GAMEPAD_START);
bool Back = (Pad->wButtons &XINPUT_GAMEPAD_BACK);
bool LeftShoulder (Pad->wButtons &XINPUT_GAMEPAD_LEFT_SHOULDER);
bool RightShoulder = (Pad->wButtons &XINPUT_GAMEPAD_RIGHT_SHOULDER);
bool AButton = (Pad->wButtons &XINPUT_GAMEPAD_A);
bool BButton = (Pad->wButtons &XINPUT_GAMEPAD_B);
bool XButton = (Pad->wButtons &XINPUT_GAMEPAD_X);
bool YButton = (Pad->wButtons &XINPUT_GAMEPAD_Y);
int16 StickX = Pad->sThumbLX;
int16 StickY = Pad->sThumbLY;
if(AButton)
{
YOffset += 2;
}

// controller is plugged in
}
else
{
//not plugged in
}


}
XINPUT_VIBRATION Vibration;
Vibration.wLeftMotorSpeed=60000;
Vibration.wRightMotorSpeed=60000;
XInputSetState(0,&Vibration);
RenderWeirdGradient(&GlobalBackbuffer,XOffset,YOffset);
win32_window_dimension Dimension = Win32GetWindowDimension(Window);
Win32DisplayBufferInWindow(DeviceContext,Dimension.Width,Dimension.Height,
GlobalBackbuffer);

++XOffset;
YOffset += 2;
}

}
else
{
}

}


else
{
}
// MessageBox(0,"This is a window.","My Window",MB_OK|MB_ICONINFORMATION);

return (0);



}

Mārtiņš Možeiko
2559 posts / 2 projects
Problem with rendering window
Edited by Mārtiņš Možeiko on
Please use [ code ] bbtags or put it in gist.github.com or similar code snipper site. It's super hard to read it without indentation.

The mistake is here:
1
Result.Width= ClientRect.right=ClientRect.left;

How can you find similar mistakes yourself in future more easier? By using debugger. When something doesn't work as expected you need to step through code and verify what it does. Verify control flow, that all conditions are correct. Verify variables that they have reasonable values. In this case you would notice that Result.Width is assigned 0 which will make nothing to appear on screen.
chodish
3 posts
Problem with rendering window
Thank you for the help and advice.