1 // Released to the Public Domain by Doug Lyons on April 16th, 2024.
2 
3 #include <windows.h>
4 #include <stdio.h>
5 
6 WCHAR szWindowClass[] = L"testclass";
7 
8 static LRESULT CALLBACK
9 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
10 {
11     static HBITMAP hBmp;
12     HANDLE handle;
13     CHAR buffer[32];
14 
15     switch (message)
16     {
17         case WM_CREATE:
18         {
19             handle = LoadLibraryExW(L"image.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
20             sprintf(buffer, "%p", handle);
21             MessageBoxA(NULL, buffer, "handle", 0);
22             hBmp = (HBITMAP)LoadImage(handle, MAKEINTRESOURCE(130), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
23             sprintf(buffer, "%p", hBmp);
24             MessageBoxA(NULL, buffer, "Bmp", 0);
25             sprintf(buffer, "%ld", GetLastError());
26             MessageBoxA(NULL, buffer, "LastError", 0);
27             break;
28         }
29 
30         case WM_PAINT:
31         {
32             PAINTSTRUCT ps;
33             HDC hdc, hdcMem;
34             BITMAP bitmap;
35             BITMAPINFO bmi;
36             hdc = BeginPaint(hWnd, &ps);
37             HGLOBAL hMem;
38             LPVOID lpBits;
39 
40             hdcMem = CreateCompatibleDC(hdc);
41             SelectObject(hdcMem, hBmp);
42             GetObject(hBmp, sizeof(BITMAP), &bitmap);
43 
44             memset(&bmi, 0, sizeof(bmi));
45             bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
46             bmi.bmiHeader.biWidth       = bitmap.bmWidth;
47             bmi.bmiHeader.biHeight      = bitmap.bmHeight;
48             bmi.bmiHeader.biPlanes      = bitmap.bmPlanes;
49             bmi.bmiHeader.biBitCount    = bitmap.bmBitsPixel;
50             bmi.bmiHeader.biCompression = BI_RGB;
51             bmi.bmiHeader.biSizeImage   = 0;
52 
53             hMem = GlobalAlloc(GMEM_MOVEABLE, ((bitmap.bmWidth *
54                 bmi.bmiHeader.biBitCount + 31) / 32) * 4 * bitmap.bmHeight);
55             lpBits = GlobalLock(hMem);
56             GetDIBits(hdc, hBmp, 0, bitmap.bmHeight, lpBits, &bmi, DIB_RGB_COLORS);
57 
58             // increasing the multiplier makes the image larger
59             StretchDIBits(hdc, 0, 0, bitmap.bmWidth * 3, bitmap.bmHeight * 3, 0, 0,
60                 bitmap.bmWidth, bitmap.bmHeight,lpBits, &bmi, DIB_RGB_COLORS, SRCCOPY);
61             GlobalUnlock(hMem);
62             GlobalFree(hMem);
63 
64             DeleteDC(hdcMem);
65 
66             EndPaint(hWnd, &ps);
67             break;
68         }
69 
70         case WM_DESTROY:
71             PostQuitMessage(0);
72             break;
73         default:
74             return DefWindowProc(hWnd, message, wParam, lParam);
75     }
76     return 0;
77 }
78 
79 
80 static ATOM
81 MyRegisterClass(HINSTANCE hInstance)
82 {
83     WNDCLASSEX wcex;
84 
85     wcex.cbSize = sizeof(WNDCLASSEX);
86 
87     wcex.style         = CS_HREDRAW | CS_VREDRAW;
88     wcex.lpfnWndProc   = WndProc;
89     wcex.cbClsExtra    = 0;
90     wcex.cbWndExtra    = 0;
91     wcex.hInstance     = hInstance;
92     wcex.hIcon         = NULL;
93     wcex.hCursor       = LoadCursor(NULL, IDC_ARROW);
94     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
95     wcex.lpszMenuName  = NULL;
96     wcex.lpszClassName = szWindowClass;
97     wcex.hIconSm       = NULL;
98 
99     return RegisterClassEx(&wcex);
100 }
101 
102 
103 static BOOL
104 InitInstance(HINSTANCE hInstance, int nCmdShow)
105 {
106     HWND hWnd;
107 
108     hWnd = CreateWindowEx(0,
109                           szWindowClass,
110                           L"Bmp test",
111                           WS_OVERLAPPEDWINDOW,
112                           CW_USEDEFAULT,
113                           CW_USEDEFAULT,
114                           300,
115                           120,
116                           NULL,
117                           NULL,
118                           hInstance,
119                           NULL);
120 
121     if (!hWnd)
122         return FALSE;
123 
124     ShowWindow(hWnd, nCmdShow);
125     UpdateWindow(hWnd);
126 
127     return TRUE;
128 }
129 
130 int WINAPI
131 wWinMain(HINSTANCE hInstance,
132     HINSTANCE hPrevInstance,
133     LPTSTR    lpCmdLine,
134     int       nCmdShow)
135 {
136     MSG msg;
137 
138     MyRegisterClass(hInstance);
139 
140     if (!InitInstance(hInstance, nCmdShow))
141         return FALSE;
142 
143     while (GetMessage(&msg, NULL, 0, 0))
144     {
145         TranslateMessage(&msg);
146         DispatchMessage(&msg);
147     }
148 
149     return (int)msg.wParam;
150 }
151