Advertisement

Drawing a buffer to client window in winapi.

Started by April 26, 2018 10:26 PM
4 comments, last by Weird buffalo 11454 6 years, 9 months ago

Objective :

I want to draw a buffer of pixel (DWORD buf[WIDTH*HEIGHT]) to the whole client window. I am somewhat familiar with Winapi but not with GDI, reading the MSDN and other sources on the internet, I have came up with the following program.  

 

Problem :

The code is not working. I have initialised all elements of my buffer ( buf[] )  to 0. So I should get a black screen on my window, but I getting a regular white window. Can somebody point me what's wrong am I doing ?

 

Code :

#include<Windows.h>
#include "stdafx.h"

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

const int HEIGHT = 512;
const int WIDTH = 512;

DWORD buf[WIDTH * HEIGHT];
BITMAPINFO bmi = { 0 };
HDC hWinDC = NULL;
HDC hbitDC = NULL;
HBITMAP hBitmap = NULL;

int WINAPI wWinMain(HINSTANCE hInstace, HINSTANCE hPrevInstace, LPWSTR lpCmdLine, int nCmdShow) {
    memset(buf, 0, sizeof(buf)/sizeof(DWORD));
    MSG msg = { 0 };
    WNDCLASS wnd = { 0 };

    wnd.lpfnWndProc = WndProc;
    wnd.hInstance = hInstace;
    wnd.lpszClassName = L"Window";

    if (!RegisterClass(&wnd)) {
        return 0;
    }

    HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, wnd.lpszClassName, L"Window",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL, NULL, hInstace, NULL);

    if (!hwnd) {
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

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

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
    HDC hWdc = NULL;
    switch (msg){

        case WM_CREATE:
            bmi.bmiHeader.biSize = sizeof(BITMAPCOREHEADER);
            bmi.bmiHeader.biWidth = WIDTH;
            bmi.bmiHeader.biHeight = HEIGHT;
            bmi.bmiHeader.biPlanes = 1;
            bmi.bmiHeader.biBitCount = 32;
            bmi.bmiHeader.biCompression = BI_RGB;

            break;

        case WM_PAINT:
            PAINTSTRUCT ps;
            hWdc = BeginPaint(hwnd, &ps);
            hWinDC = GetDC(hwnd);
            hbitDC = CreateCompatibleDC(hWinDC);

            hBitmap = CreateDIBSection(hWinDC, &bmi, DIB_RGB_COLORS, (void**)&buf, NULL, NULL);

            SelectObject(hbitDC, hBitmap);

            BitBlt(hWdc, 0, 0, WIDTH, HEIGHT, hbitDC, 0, 0, SRCCOPY);
            EndPaint(hwnd, &ps);
            break;

        case WM_KEYUP:
            if (wParam == 0x41) {
                SendMessage(hwnd, WM_PAINT, NULL, NULL);
            }
            break;
        case WM_DESTROY:
            DeleteDC(hbitDC);
            ReleaseDC(hwnd, hWinDC);

            PostQuitMessage(0);
            break;
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

 

 

Have you set a break point inside the WM_PAINT case?  Does it properly break into it when you press up?

Next time, the <>'s are used for posting code, they're along the top of the window when writing your post.  Makes things easier to read and formats it better in most instances too.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

Advertisement

Sorry to hit and run, I'm literally about to run out the door, but you can check out some code I have which does exactly this here:

https://github.com/GeneralLeeInept/vgfw/blob/master/vgfw.h

 

I have code for doing this in asm:

https://github.com/phreda4/reda4/blob/master/r4asm/r4fasm.asm

or the interpreter in c, but with some more things, in

https://github.com/phreda4/r4MV/blob/master/r4wine2/graf.cpp

 

try

 


 bmi.bmiHeader.biHeight = -HEIGHT;

minus!!!


#include<Windows.h>
#include "stdafx.h"
#include "Global.h"

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void initBackBuffer(HWND hwnd);


HDC hBackDC = NULL;
HBITMAP hBackBitmap = NULL;
BITMAPINFO bmi = { 0 };

void draw(HWND hwnd) {
	SetBitmapBits(hBackBitmap, HEIGHT * WIDTH, (const void*)(screenBuffer));
	BitBlt(GetDC(hwnd), 0, 0, WIDTH, HEIGHT, hBackDC, 0, 0, SRCCOPY);
}

int WINAPI wWinMain(HINSTANCE hInstace, HINSTANCE hPrevInstace, LPWSTR lpCmdLine, int nCmdShow) {
	memset(screenBuffer, 0, sizeof(screenBuffer));
	MSG msg = { 0 };
	WNDCLASS wnd = { 0 };

	wnd.lpfnWndProc = WndProc;
	wnd.hInstance = hInstace;
	wnd.lpszClassName = L"Window";

	if (!RegisterClass(&wnd)) {
		return 0;
	}

	HWND hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, wnd.lpszClassName, L"Window",
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL, NULL, hInstace, NULL);

	if (!hwnd) {
		return 0;
	}

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);

	drawPixel(10, 0, 0x00FF0000);
	drawPixel(10, 100, 0x0000FF00);
	drawPixel(10, 10, 0x000000FF);
	
	while (true) {
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
			if (msg.message == WM_QUIT) {
				break;
			}

			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		

		draw(hwnd);
	}

	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){

	switch (msg){
		case WM_CREATE:
			initBackBuffer(hwnd);
			break;
		case WM_DESTROY:
			DeleteDC(hBackDC);
			DeleteObject(hBackBitmap);
			PostQuitMessage(0);
			break;
	}
	return DefWindowProc(hwnd, msg, wParam, lParam);
}

void initBackBuffer(HWND hwnd) {
	HDC hWinDC = GetDC(hwnd);

	BITMAPINFO bmi = { 0 };
	bmi.bmiHeader.biSize = sizeof(BITMAPCOREHEADER);
	bmi.bmiHeader.biWidth = WIDTH;
	bmi.bmiHeader.biHeight = -HEIGHT;
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;
	bmi.bmiHeader.biCompression = BI_RGB;

	hBackDC = CreateCompatibleDC(hWinDC);
	hBackBitmap = CreateCompatibleBitmap(hWinDC, WIDTH, HEIGHT); 
	SetBitmapBits(hBackBitmap, HEIGHT * WIDTH, (const void*)(screenBuffer));
	
	SelectObject(hBackDC, hBackBitmap);
	ReleaseDC(hwnd, hWinDC);
}

 

Global.h


#pragma once
#include "stdafx.h"

const int WIDTH = 512;
const int HEIGHT = 512;

DWORD screenBuffer[WIDTH * HEIGHT];

inline void drawPixel(unsigned int x, unsigned int y, DWORD color) {
	screenBuffer[y * WIDTH + x] = color;
}

 

Thank you all.

I think I finally got it working, I used just 'SetBitmapBits' instead of all that 'CreateDIBSection' clutter. Can somebody please check if this is fine or not ?

This topic is closed to new replies.

Advertisement