Before I begin, I should mention that this code was not written by me, but it does what I need. I've only read a little about DIB's and was experimenting with some different examples, but most of them tend to use 24bpp bitmaps. I want to use an 8bpp compressed bitmap to reduce its size in my executable. The program compiles but doesn't display it. What is missing here? The code will work fine with a 24bpp bitmap.
#include <windows.h>
#include "resource.h"
struct BACKBUFFER {
HWND hwnd;
HDC hdc;
HBITMAP hbmp;
HBITMAP hbmpPrev;
HBRUSH hbr;
int cx;
int cy;
};
typedef struct BACKBUFFER BACKBUFFER;
struct OBJECT {
HDC hdc;
HBITMAP hbmp;
HBITMAP hbmpPrev;
BOOL bUp;
int nBright;
int x;
int y;
int cx;
int cy;
};
typedef struct OBJECT OBJECT;
BOOL g_bPause = FALSE;
BOOL g_bLostFocus = FALSE;
BACKBUFFER g_backBuffer = {0};
OBJECT g_object = {0};
int Run(void);
BOOL CreateBackbuffer(HWND hwnd);
void DestroyBackbuffer();
BOOL CreateObject(HWND hwnd);
void DestroyObject();
void Move(void);
void Render(void);
void Show(void);
BYTE ArrangeBright(BYTE color, BYTE bright);
void CopyBits(HBITMAP hbmpDest, int xStart, int yStart, int cx, int cy, HBITMAP hbmpSrc, BYTE bright);
LPBYTE GetBits(HBITMAP hbmp, int x, int y);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
TCHAR szAppName[] = TEXT("RGB Fade");
HWND hwnd;
WNDCLASSEX wc;
RECT rc;
DWORD dwStyle;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinst;
wc.hIcon = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
wc.hCursor = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szAppName;
wc.hIconSm = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
if (RegisterClassEx(&wc) == 0)
return 0;
dwStyle = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX;
SetRect(&rc, 0, 0, 320, 175);
AdjustWindowRect(&rc, dwStyle, FALSE);
hwnd = CreateWindowEx(0, szAppName, szAppName, dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hinst, NULL);
if (hwnd == NULL)
return 0;
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return Run();
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_CREATE:
if (!CreateBackbuffer(hwnd))
return -1;
if (!CreateObject(hwnd))
return -1;
return 0;
case WM_KEYDOWN:
if (wParam == VK_PAUSE) {
g_bPause = !g_bPause;
if (g_bPause)
Show();
}
return 0;
case WM_PAINT:
Show();
break;
case WM_NCLBUTTONDOWN:
Show();
break;
case WM_ERASEBKGND:
return 0;
case WM_SETFOCUS:
g_bLostFocus = FALSE;
return 0;
case WM_KILLFOCUS:
g_bLostFocus = TRUE;
return 0;
case WM_DESTROY:
DestroyBackbuffer();
DestroyObject();
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int Run(void)
{
MSG msg;
BOOL bMove;
DWORD dwInterval = 40;
DWORD dwCurTime, dwNextTime;
bMove = TRUE;
dwNextTime = timeGetTime();
for (;;) {
if (g_bPause || g_bLostFocus || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
if (GetMessage(&msg, NULL, 0, 0) > 0)
DispatchMessage(&msg);
else
break;
}
else {
if (bMove) {
Move();
Render();
bMove = FALSE;
}
dwCurTime = timeGetTime();
if (dwCurTime > dwNextTime) {
Show();
dwNextTime += dwInterval;
if (dwNextTime < dwCurTime)
dwNextTime = dwCurTime + dwInterval;
bMove = TRUE;
}
else
Sleep(dwNextTime - dwCurTime);
}
}
return (int)msg.wParam;
}
BOOL CreateBackbuffer(HWND hwnd)
{
HDC hdc;
LPVOID lp;
BITMAPINFO bmi;
BITMAPINFOHEADER bmiHeader;
ZeroMemory(&bmiHeader, sizeof(BITMAPINFOHEADER));
bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = 320;
bmiHeader.biHeight = 175;
bmiHeader.biPlanes = 1;
bmiHeader.biBitCount = 24;
bmi.bmiHeader = bmiHeader;
g_backBuffer.hbmp = CreateDIBSection(NULL, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS, &lp, NULL, 0);
if (g_backBuffer.hbmp == NULL)
return FALSE;
hdc = GetDC(hwnd);
g_backBuffer.hdc = CreateCompatibleDC(hdc);
g_backBuffer.hbmpPrev = (HBITMAP)SelectObject(g_backBuffer.hdc, g_backBuffer.hbmp);
ReleaseDC(hwnd, hdc);
g_backBuffer.hwnd = hwnd;
g_backBuffer.hbr = (HBRUSH)GetStockObject(BLACK_BRUSH);
g_backBuffer.cx = 320;
g_backBuffer.cy = 175;
return TRUE;
}
void DestroyBackbuffer()
{
if (g_backBuffer.hdc != NULL) {
if (g_backBuffer.hbmp != NULL) {
SelectObject(g_backBuffer.hdc, g_backBuffer.hbmpPrev);
DeleteObject(g_backBuffer.hbmp);
}
DeleteDC(g_backBuffer.hdc);
}
}
BOOL CreateObject(HWND hwnd)
{
HDC hdc;
BITMAP bm;
hdc = GetDC(hwnd);
g_object.hdc = CreateCompatibleDC(hdc);
g_object.hbmp = (HBITMAP)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_PIC), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
if (g_object.hbmp == NULL) {
ReleaseDC(hwnd, hdc);
return FALSE;
}
g_object.hbmpPrev = (HBITMAP)SelectObject(g_object.hdc, g_object.hbmp);
g_object.bUp = FALSE;
g_object.nBright = 0;
GetObject(g_object.hbmp, sizeof(BITMAP), &bm);
g_object.x = 0;
g_object.y = 0;
g_object.cx = bm.bmWidth;
g_object.cy = bm.bmHeight;
ReleaseDC(hwnd, hdc);
return TRUE;
}
void DestroyObject()
{
if (g_object.hdc != NULL) {
if (g_object.hbmp != NULL) {
SelectObject(g_object.hdc, g_object.hbmpPrev);
DeleteObject(g_object.hbmp);
}
DeleteDC(g_object.hdc);
}
}
void Move(void)
{
int nSpeed = 1;
if (GetAsyncKeyState(VK_SPACE) < 0)
nSpeed = 3;
if (g_object.bUp) {
g_object.nBright += 2 * nSpeed;
if (g_object.nBright >= 255) {
g_object.bUp = FALSE;
g_object.nBright = 255;
}
}
else {
g_object.nBright -= 2 * nSpeed;
if (g_object.nBright <= 0) {
g_object.bUp = TRUE;
g_object.nBright = 0;
}
}
}
void Render(void)
{
RECT rc;
SetRect(&rc, 0, 0, g_backBuffer.cx, g_backBuffer.cy);
FillRect(g_backBuffer.hdc, &rc, g_backBuffer.hbr);
CopyBits(g_backBuffer.hbmp, g_object.x, g_object.y, g_object.cx, g_object.cy, g_object.hbmp, (BYTE)g_object.nBright);
}
void Show(void)
{
HDC hdc;
hdc = GetDC(g_backBuffer.hwnd);
BitBlt(hdc, 0, 0, g_backBuffer.cx, g_backBuffer.cy, g_backBuffer.hdc, 0, 0, SRCCOPY);
ReleaseDC(g_backBuffer.hwnd, hdc);
}
BYTE ArrangeBright(BYTE color, BYTE bright)
{
if (bright > 128)
color += ((255 - color) * (bright - 127)) / 128;
else
color = color * bright / 128;
return color;
}
void CopyBits(HBITMAP hbmpDest, int xStart, int yStart, int cx, int cy, HBITMAP hbmpSrc, BYTE bright)
{
int x, y;
LPBYTE lpSrc, lpDest;
for (y = 0; y < cy; y++) {
lpSrc = GetBits(hbmpSrc, 0, y);
lpDest = GetBits(hbmpDest, xStart, yStart + y);
for (x = 0; x < cx; x++) {
lpDest[0] = ArrangeBright(lpSrc[0], bright);
lpDest[1] = ArrangeBright(lpSrc[1], bright);
lpDest[2] = ArrangeBright(lpSrc[2], bright);
lpSrc += 3;
lpDest += 3;
}
}
}
LPBYTE GetBits(HBITMAP hbmp, int x, int y)
{
BITMAP bm;
LPBYTE lp;
GetObject(hbmp, sizeof(BITMAP), &bm);
lp = (LPBYTE)bm.bmBits;
lp += (bm.bmHeight - y - 1) * ((3 * bm.bmWidth + 3) / 4) * 4;
lp += 3 * x;
return lp;
}