I am using C and C++, whichever works. Prefer Win32 if that works. CodeBlocks. No dot net. No visual studio. No MFC.
I tried writing this on my own, but it is beyond me.
My latest attempt has been the following:
I have been studying DrawText function from microsoft.com to write text to a bitmap.
Then I tried using similar to from stackoverflow.c om but I did not get that to work. My compiler chokes on that. I tried studying that and fixing it, but my many attempts did not work.
Also, I tried adjusting this another from codeproject.com from whatever that is written in. I think it is MFC or cling-on or confused-us or something. My compiler pukes out almost every line of that.
Now I have this:
It does not work.
I tried various adjustments. I studied what the debugger said. I am getting overwhelmed by this. Would you please help me to get this to work?
Thank you.
In case you want more to see what I have: This is my entire program. It currently shows some red text on a bitmap that I have used to create a custom region. That works. But, I want to be able to use that and bitblt the blank bmp background out of it and just leave the text for my program to show. My intent is to have just the text showing with a transparent background. I want to make this dynamically. NOT in some image editor. I want to be able to show a changing text. That is where I am going with this. Help! Please!
And then:
And then more:
Also:
And last:
Oh, the picture that I am working on: It is local and I did not get it to upload to here. Just pick a bmp and use it yourself.
I tried writing this on my own, but it is beyond me.
My latest attempt has been the following:
I have been studying DrawText function from microsoft.com to write text to a bitmap.
Then I tried using similar to from stackoverflow.c om but I did not get that to work. My compiler chokes on that. I tried studying that and fixing it, but my many attempts did not work.
Also, I tried adjusting this another from codeproject.com from whatever that is written in. I think it is MFC or cling-on or confused-us or something. My compiler pukes out almost every line of that.
Now I have this:
Code:
HBITMAP hbitmap = hMainWindowBitmapForRegion;
// MAKEINTRESOURCE(IDB_BITMAP1));
//BITMAP bm;
GetObject( hbitmap, sizeof(BITMAP), &bm );
long width=bm.bmWidth;
long height=bm.bmHeight;
//prepare the bitmap attributes
BITMAPINFO bmInfo;
memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biWidth=width;
bmInfo.bmiHeader.biHeight=height;
bmInfo.bmiHeader.biPlanes=1;
bmInfo.bmiHeader.biBitCount=24;
//create a temporary dc in memory.
HDC pDC = ::GetDC(0);
HDC TmpDC=CreateCompatibleDC(pDC);
//create a new bitmap and select it in the memory dc
BYTE *pbase;
HBITMAP TmpBmp=CreateDIBSection(pDC,
&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
//draw the background
HDC dcBmp=CreateCompatibleDC(TmpDC);
HGDIOBJ TmpObj2 = SelectObject(dcBmp,hbitmap);
BitBlt(TmpDC,0,0,width,height,dcBmp,0,0,SRCCOPY);
SelectObject(TmpDC,TmpObj2);
DeleteDC(dcBmp);
//choose the font
//CFont m_Font;
HFONT m_Font; // = (HFONT)lParam;
LOGFONT* m_pLF;
m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));
HFONT hFont = CreateFont (13, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET,
OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, TEXT("Tahoma"));
//Set text position;
RECT pos = {40,40,50,50};
//draw the text
HDC dcBmp2=CreateCompatibleDC(TmpDC);
SetTextColor(dcBmp2,RGB(0,255,0));
SetBkMode(dcBmp2, TRANSPARENT);
SetBkColor(dcBmp2,RGB(0,0,255));
//SetBkMode(TRANSPARENT);
DrawTextW(dcBmp2,(LPCWSTR)"TestTestTestTestTestTestTestTestTestTestTest",4,&pos,DT_CALCRECT);
DrawTextW(dcBmp2,(LPCWSTR)"TestTestTestTestTestTestTestTestTestTestTest",4,&pos,0);
//cleanup
free(m_pLF);
DeleteDC(dcBmp2);
I tried various adjustments. I studied what the debugger said. I am getting overwhelmed by this. Would you please help me to get this to work?
Thank you.
In case you want more to see what I have: This is my entire program. It currently shows some red text on a bitmap that I have used to create a custom region. That works. But, I want to be able to use that and bitblt the blank bmp background out of it and just leave the text for my program to show. My intent is to have just the text showing with a transparent background. I want to make this dynamically. NOT in some image editor. I want to be able to show a changing text. That is where I am going with this. Help! Please!
Code:
// BitmapToCustomShapedRegion.cpp
#define _UNICODE
#define UNICODE
#define STRICT // Require more care in declaring and using types.
#include <windows.h>
#include <string> // for std::char_traits
//#include <iostream> // std::cout
#include <algorithm> // std::min
// Globals
TCHAR szClassName[] = L"WIN32TEST";
HWND Handle_of_MainWindow;
HDC HDC_of_MainWindow;
HINSTANCE MainWindow_hInstance;
// Function prototypes with default arguments
HBITMAP hMainWindowBitmapForRegion;
BITMAPINFOHEADER RGB32BITSBITMAPINFO;
#include "resource.h"
#include "bitmap_to_region.h"
#include "callback_winproc_main.h"
//#include "ShObjIdl.h"
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Parameters being set but maybe not being used
HINSTANCE hNotUsing001;
hNotUsing001 = hPrevInstance;
hPrevInstance = hNotUsing001;
LPSTR lpNotUsing002;
lpNotUsing002 = lpCmdLine;
lpCmdLine = lpNotUsing002;
// Parameters being set and being used
WNDCLASS wc;
HWND hWnd;
MSG msg;
// HBITMAP hMainWindowBitmapForRegion;
hMainWindowBitmapForRegion = (HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
HWND HWND_of_TestBitmap_001= (HWND)hMainWindowBitmapForRegion;
if (hMainWindowBitmapForRegion)
{
ZeroMemory(&wc, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = (WNDPROC)WndProc_for_main;
wc.hInstance = hInstance;
if (RegisterClass(&wc))
{
BITMAP bm;
GetObject(hMainWindowBitmapForRegion, sizeof(bm), &bm);
// For Agents
//hWnd = CreateWindow(szClassName, NULL, WS_POPUP, 100, 10, bm.bmWidth, bm.bmHeight, NULL, NULL, hInstance, NULL);
// For Anti-Agents
hWnd = CreateWindow(szClassName, NULL, WS_POPUP, 650, 10, bm.bmWidth, bm.bmHeight, NULL, NULL, hInstance, NULL);
/// test..........START
HBITMAP hbitmap = hMainWindowBitmapForRegion;
//BITMAP bm;
GetObject( hbitmap, sizeof(BITMAP), &bm );
long width=bm.bmWidth;
long height=bm.bmHeight;
//prepare the bitmap attributes
BITMAPINFO bmInfo;
memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biWidth=width;
bmInfo.bmiHeader.biHeight=height;
bmInfo.bmiHeader.biPlanes=1;
bmInfo.bmiHeader.biBitCount=24;
//create a temporary dc in memory.
HDC pDC = ::GetDC(0);
HDC TmpDC=CreateCompatibleDC(pDC);
//create a new bitmap and select it in the memory dc
BYTE *pbase;
HBITMAP TmpBmp=CreateDIBSection(pDC,
&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
//draw the background
HDC dcBmp=CreateCompatibleDC(TmpDC);
HGDIOBJ TmpObj2 = SelectObject(dcBmp,hbitmap);
BitBlt(TmpDC,0,0,width,height,dcBmp,0,0,SRCCOPY);
SelectObject(TmpDC,TmpObj2);
DeleteDC(dcBmp);
//choose the font
HFONT m_Font;
LOGFONT* m_pLF;
m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));
HFONT hFont = CreateFont (13, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET,
OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, TEXT("Tahoma"));
//Set text position;
RECT pos = {40,40,50,50};
//draw the text
HDC dcBmp2=CreateCompatibleDC(TmpDC);
SetTextColor(dcBmp2,RGB(0,255,0));
SetBkMode(dcBmp2, TRANSPARENT);
SetBkColor(dcBmp2,RGB(0,0,255));
//SetBkMode(TRANSPARENT);
DrawTextW(dcBmp2,(LPCWSTR)"TestTestTestTestTestTestTestTestTestTestTest",4,&pos,DT_CALCRECT);
DrawTextW(dcBmp2,(LPCWSTR)"TestTestTestTestTestTestTestTestTestTestTest",4,&pos,0);
//cleanup
free(m_pLF);
DeleteDC(dcBmp2);
/// test..........END
if (hWnd)
{
Handle_of_MainWindow = hWnd; // Using this for closing the program.
HDC_of_MainWindow = GetDC( Handle_of_MainWindow );
MainWindow_hInstance = hInstance;
HRGN hBtRgn = BitmapToRegion(hMainWindowBitmapForRegion);
if (hBtRgn)
{
SetWindowRgn(hWnd, hBtRgn, TRUE);
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (msg.wParam);
}
}
}
return 0; // successfully executed.
// The return value is the exit code of your program, the shell
// (or any other application that ran it) can read and use it.
// nonzero indicates a failure of some kind.
// return 1; // executed but some error may have occured.
// return -1; // unexpected error may have occured.
}
And then:
Code:
// bitmap_to_region.h
//
// BitmapToRegion : Create a region from the "non-transparent" pixels of a bitmap
// Author : Jean-Edouard Lachand-Robert (http://www.geocities.com/Paris/LeftBank/1160/resume.htm), June 1998.
//
// hMainWindowBitmapForRegion : Handle of a source bitmap
// cTransparentColor : Color base for the "transparent" pixels (default is black)
// cTolerance : Color tolerance for the "transparent" pixels.
//
// A pixel is assumed to be transparent if the value of each of its 3 components (blue, green and red) is
// greater or equal to the corresponding value in cTransparentColor and is lower or equal to the
// corresponding value in cTransparentColor + cTolerance.
//
COLORREF cTransparentColor = RGB(254, 243, 222); // Used as Blue Green Red
COLORREF cTolerance = 0x000000;
// Previous declaration
HRGN BitmapToRegion (HBITMAP hReceivedBitmap);
HRGN BitmapToRegion (HBITMAP hReceivedBitmap)
{
HRGN hRgn = NULL;
if (hReceivedBitmap)
{
// Create a memory DC inside which we will scan the bitmap content
HDC hMemDC = CreateCompatibleDC(nullptr);
if (hMemDC)
{
// Get bitmap size
BITMAP bm;
GetObject(hReceivedBitmap, sizeof(bm), &bm);
// Create a 32 bits depth bitmap and select it into the memory DC
//BITMAPINFOHEADER RGB32BITSBITMAPINFO;
RGB32BITSBITMAPINFO = {
sizeof(BITMAPINFOHEADER), // biSize
bm.bmWidth, // biWidth;
bm.bmHeight, // biHeight;
1, // biPlanes;
32, // biBitCount
BI_RGB, // biCompression;
0, // biSizeImage;
0, // biXPelsPerMeter;
0, // biYPelsPerMeter;
0, // biClrUsed;
0 // biClrImportant;
};
// VOID * pbits32;
// HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, &pbits32, nullptr, 0);
HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, nullptr, nullptr, 0);
if (hbm32)
{
HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);
// Create a DC just to copy the bitmap into the memory DC
HDC hDC = CreateCompatibleDC(hMemDC);
if (hDC)
{
// Get how many bytes per row we have for the bitmap bits (rounded up to 32 bits)
BITMAP bm32;
GetObject(hbm32, sizeof(bm32), &bm32);
while (bm32.bmWidthBytes % 4)
bm32.bmWidthBytes++;
// Copy the bitmap into the memory DC
holdBmp = (HBITMAP)SelectObject(hDC, hReceivedBitmap);
BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, hDC, 0, 0, SRCCOPY);
// For better performances, we will use the ExtCreateRegion() function to create the
// region. This function take a RGNDATA structure on entry. We will add rectangles by
// amount of ALLOC_UNIT number in this structure.
#define ALLOC_UNIT 1000
DWORD maxRects = ALLOC_UNIT;
HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects));
RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
pData->rdh.dwSize = sizeof(RGNDATAHEADER);
pData->rdh.iType = RDH_RECTANGLES;
pData->rdh.nCount = pData->rdh.nRgnSize = 0;
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
// Keep on hand highest and lowest values for the "transparent" pixels
BYTE lr = GetRValue(cTransparentColor);
BYTE lg = GetGValue(cTransparentColor);
BYTE lb = GetBValue(cTransparentColor);
BYTE hr = std::min(0xff, lr + GetRValue(cTolerance));
BYTE hg = std::min(0xff, lg + GetGValue(cTolerance));
BYTE hb = std::min(0xff, lb + GetBValue(cTolerance));
// Scan each bitmap row from bottom to top (the bitmap is inverted vertically)
BYTE *p32 = (BYTE *)bm32.bmBits + (bm32.bmHeight - 1) * bm32.bmWidthBytes;
for (int y = 0; y < bm.bmHeight; y++)
{
// Scan each bitmap pixel from left to right
for (int x = 0; x < bm.bmWidth; x++)
{
// Search for a continuous range of "non transparent pixels"
int x0 = x;
LONG *p = (LONG *)p32 + x;
while (x < bm.bmWidth)
{
BYTE b = GetRValue(*p);
if (b >= lr && b <= hr)
{
b = GetGValue(*p);
if (b >= lg && b <= hg)
{
b = GetBValue(*p);
if (b >= lb && b <= hb)
{
// This pixel is "transparent"
break;
}
}
}
p++;
x++;
}
if (x > x0)
{
// Add the pixels (x0, y) to (x, y+1) as a new rectangle in the region
if (pData->rdh.nCount >= maxRects)
{
GlobalUnlock(hData);
maxRects += ALLOC_UNIT;
hData = GlobalReAlloc(hData, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), GMEM_MOVEABLE);
pData = (RGNDATA *)GlobalLock(hData);
}
RECT *pr = (RECT *)&pData->Buffer;
SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
if (x0 < pData->rdh.rcBound.left)
{
pData->rdh.rcBound.left = x0;
}
if (y < pData->rdh.rcBound.top)
{
pData->rdh.rcBound.top = y;
}
if (x > pData->rdh.rcBound.right)
{
pData->rdh.rcBound.right = x;
}
if (y+1 > pData->rdh.rcBound.bottom)
{
pData->rdh.rcBound.bottom = y+1;
}
pData->rdh.nCount++;
// On Windows 98, ExtCreateRegion() may fail if the number of rectangles is too
// large (ie: > 4000). Therefore, we have to create the region by multiple steps.
if (pData->rdh.nCount == 2000)
{
HRGN h = ExtCreateRegion(nullptr, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else
{
hRgn = h;
pData->rdh.nCount = 0;
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
}
}
}
}
// Go to next row (remember, the bitmap is inverted vertically)
p32 -= bm32.bmWidthBytes;
}
// Create or extend the region with the remaining rectangles
HRGN h = ExtCreateRegion(nullptr, sizeof(RGNDATAHEADER) + (sizeof(RECT) * maxRects), pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else
{
hRgn = h;
}
// Clean up
SelectObject(hDC, holdBmp);
DeleteDC(hDC);
}
DeleteObject(SelectObject(hMemDC, holdBmp));
}
DeleteDC(hMemDC);
}
}
return hRgn;
}
And then more:
Code:
// callback_winproc_main.h
///
// Previous declaration
LRESULT CALLBACK WndProc_for_main(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProc_for_main(
HWND hWnd, // A handle to the window procedure to receive the message.
UINT message, // The message.
WPARAM wParam, // Additional message-specific information. The contents of this parameter depend on the value of the Msg parameter.
LPARAM lParam // Additional message-specific information. The contents of this parameter depend on the value of the Msg parameter.
)
// The return value specifies the result of the message processing and depends on the message sent.
// WNDPROC is either the address of a window or dialog box procedure,
// or a special internal value meaningful only to CallWindowProc.
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_NCHITTEST:
{
return HTCAPTION;
}
case WM_LBUTTONDOWN:
{
break;
}
case WM_PAINT:
{
hdc = BeginPaint (hWnd, &ps);
if (hMainWindowBitmapForRegion)
{
BITMAP bm;
GetObject(hMainWindowBitmapForRegion, sizeof(bm), &bm);
HDC memdc = CreateCompatibleDC(nullptr);
HBITMAP h = (HBITMAP)SelectObject(memdc, hMainWindowBitmapForRegion);
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, memdc, 0, 0, SRCCOPY);
SelectObject(memdc, h);
}
/// THIS WORKS !
/// Text to the bitmap START
HDC hMemDC = CreateCompatibleDC(nullptr);
HBITMAP hbm32 = CreateDIBSection(hMemDC, (BITMAPINFO *)&RGB32BITSBITMAPINFO, DIB_RGB_COLORS, nullptr, nullptr, 0);
HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);
SelectObject(hdc, (HGDIOBJ) holdBmp);
HINSTANCE hInstance_of_TestBitmap_001 = GetModuleHandleW(L"Anti-Agent_Belinda.bmp");
LPCWSTR SomeLText = L"1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z";
int LengthOfSomeLText = std::char_traits<wchar_t>::length (SomeLText);
SetTextColor(hdc,RGB(255,0,0));
SetBkMode(hdc, TRANSPARENT);
SetBkColor(hdc,RGB(0,255,0));
for (int i = 0; i < 10; i++)
{
TextOutW ( hdc, 10, (i * 15), SomeLText, LengthOfSomeLText );
}
/// Text to the bitmap END
EndPaint (hWnd, &ps);
break;
}
case WM_KEYDOWN:
{
if (wParam != VK_ESCAPE)
{
break;
}
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
{
return (DefWindowProc(hWnd, message, wParam, lParam));
}
}
return (0);
}
Also:
Code:
// resource.h #define IDB_BITMAP1 101
And last:
Code:
// resource.rc
#include "resource.h"
// The DISCARDABLE keyword is ignored for 32-bit Windows, but remains for compatibility.
IDB_BITMAP1 BITMAP "Blank_single_color.bmp" // To have a background that I can remove later.
#define SUBLANG_NEUTRAL 0x00 // This was in winnt.h which seems to be called by afxres.h
// I do not need all of that shit for just this one line.
// I am getting tired of stripping vast amounts of Visual Studio
// crap from examples just to get to the line or lines that I need.
LANGUAGE 0, SUBLANG_NEUTRAL
Oh, the picture that I am working on: It is local and I did not get it to upload to here. Just pick a bmp and use it yourself.