- Reaction score
- 1,843
This code demonstrates the ability to use Win32 API to draw or print text to a bitmap, and then save the bitmap to a file.
Note:
Note:
- Text is pink for testing purposes.
- Text font uses the System Font.
- This is merely a demonstration (proof of concept), and may not be suitable for "best practices".
- There are many things that can be improved, such as fixing the brief moment where the text would appear on the screen.
- This program generates a bitmap, akin to doing a Print Screen, which captures the entire screen displayed on your primary monitor.
- The example code is self-documenting, which is not the best coding practice anyone should follow.
- The bitmap file, saved after executing the program, is expected to be no less than 8MB at a 1080p resolution.
- This example code is used for archival purposes, to show that printing text is possible using pure Win32 API in C / C++.
- There are no AFX or Object-Oriented Win32 stuffs in this code. This is pure Win32 code in C, with very little C++ code in it.
Code:
#include <Windows.h>
#include <iostream>
#include <fstream>
HBITMAP CaptureScreen(HDC currentDeviceContext, std::string text) {
int width = GetSystemMetrics(SM_CXSCREEN);
int height = GetSystemMetrics(SM_CYSCREEN);
HDC compatibleDeviceContext = CreateCompatibleDC(currentDeviceContext);
HBITMAP bitmapHandle = CreateCompatibleBitmap(currentDeviceContext, width, height);
HGDIOBJ previousSelectedHandle = SelectObject(compatibleDeviceContext, bitmapHandle);
BOOL result = BitBlt(compatibleDeviceContext, 0, 0, width, height, currentDeviceContext, 0, 0, SRCCOPY | CAPTUREBLT);
if (!result) {
MessageBox(nullptr, TEXT("BitBlt() fails 1."), TEXT("Error"), MB_OK);
return nullptr;
}
HFONT font = (HFONT)GetStockObject(SYSTEM_FONT);
SetTextColor(compatibleDeviceContext, RGB(255, 0, 255));
SetBkMode(compatibleDeviceContext, TRANSPARENT);
HFONT previousFont = (HFONT)SelectObject(compatibleDeviceContext, font);
TextOut(compatibleDeviceContext, 240, 360, TEXT(text.c_str()), text.size());
result = BitBlt(currentDeviceContext, 0, 0, width, height, compatibleDeviceContext, 0, 0, SRCCOPY);
if (!result) {
MessageBox(nullptr, TEXT("BitBlt() fails 2."), TEXT("Error"), MB_OK);
return nullptr;
}
SelectObject(compatibleDeviceContext, previousFont);
SelectObject(compatibleDeviceContext, previousSelectedHandle);
DeleteDC(compatibleDeviceContext);
return bitmapHandle;
}
void SaveFile(BYTE* pixels, BITMAPINFOHEADER& bitmapInfoHeader) {
HANDLE fileHandle = CreateFile(TEXT("Test.bmp"), GENERIC_READ | GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (fileHandle == INVALID_HANDLE_VALUE) {
MessageBox(nullptr, TEXT("CreateFile() failed."), TEXT("Error"), MB_OK);
return;
}
BITMAPFILEHEADER bitmapFileHeader = { 0 };
bitmapFileHeader.bfType = 0x4d42;
bitmapFileHeader.bfSize = sizeof(bitmapFileHeader) + bitmapInfoHeader.biSize + bitmapInfoHeader.biClrUsed * sizeof(RGBQUAD) + bitmapInfoHeader.biSizeImage;
bitmapFileHeader.bfReserved1 = bitmapFileHeader.bfReserved2 = 0;
bitmapFileHeader.bfOffBits = sizeof(bitmapFileHeader) + bitmapInfoHeader.biSize + bitmapInfoHeader.biClrUsed * sizeof(RGBQUAD);
DWORD tempDword;
if (!WriteFile(fileHandle, (LPVOID)&bitmapFileHeader, sizeof(bitmapFileHeader), (LPDWORD)&tempDword, nullptr)) {
MessageBox(nullptr, TEXT("WriteFile() failed 1."), TEXT("Error"), MB_OK);
return;
}
if (!WriteFile(fileHandle, (LPVOID) &bitmapInfoHeader, sizeof(bitmapInfoHeader) + bitmapInfoHeader.biClrUsed * sizeof(RGBQUAD), (LPDWORD) &tempDword, nullptr)) {
MessageBox(nullptr, TEXT("WriteFile() failed 2."), TEXT("Error"), MB_OK);
return;
}
if (!WriteFile(fileHandle, (LPVOID) pixels, (int)bitmapInfoHeader.biSizeImage, (LPDWORD) &tempDword, nullptr)) {
MessageBox(nullptr, TEXT("WriteFile() failed 3."), TEXT("Error"), MB_OK);
return;
}
if (!CloseHandle(fileHandle)) {
MessageBox(nullptr, TEXT("CloseHandle() failed."), TEXT("Error"), MB_OK);
return;
}
}
int main() {
HDC deviceContext = GetDC(nullptr);
HBITMAP capturedBitmap = CaptureScreen(deviceContext, std::string("Hello world."));
BITMAPINFO bitmapInfo = { 0 };
bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo.bmiHeader);
BOOL result = GetDIBits(deviceContext, capturedBitmap, 0, 0, nullptr, &bitmapInfo, DIB_RGB_COLORS);
if (!result) {
MessageBox(nullptr, TEXT("GetDIBits() failed."), TEXT("Error"), MB_OK);
return -1;
}
BYTE* pixels = new BYTE[bitmapInfo.bmiHeader.biSizeImage];
bitmapInfo.bmiHeader.biCompression = BI_RGB;
result = GetDIBits(deviceContext, capturedBitmap, 0, bitmapInfo.bmiHeader.biHeight, (LPVOID)pixels, &bitmapInfo, DIB_RGB_COLORS);
if (!result) {
MessageBox(nullptr, TEXT("GetDIBits(), second function, failed."), TEXT("Error"), MB_OK);
return -2;
}
SaveFile(pixels, bitmapInfo.bmiHeader);
DeleteObject(capturedBitmap);
ReleaseDC(nullptr, deviceContext);
delete[] pixels;
return 0;
}
Last edited: