This tip shows how to enter text into a static control, change the font style, then save the static control in a Windows Bitmap.
Introduction
I wanted a way to enter text into a Static Control and be able to change the font style, then save the Static Control in a Windows Bitmap.
The framework in a CDialog App
handles the Space key the same way it does the Enter key and Escape key, It ends the dialog. Also, the framework does not send a WM_CHAR
message in a dialog so I had to use PreTranslateMessage
function to handle keyboard characters being typed. One other problem solved, using SetFont(&lf)
for example, does not change the font size.
The Article Body
I did not want to "reinvent the wheel", so I used classes I found here on Code Project. The classes used are AutoFont
and Drawing2Bitmap
.
Using the Code
To initialize the bitmap and the font In OnInitDialog()
, here, usually you could use m_autofont.SetFont(&lf)
but a dialog won't let you change the font size that way.
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfHeight = 160;
_tcsncpy_s(lf.lfFaceName, LF_FACESIZE, _T("Consolas"), 9);
m_autofont.CreatePointFontIndirect(&lf);
StaticWnd.GetClientRect(&m_rcStaticWnd);
CDC* pDC = GetDC();
if(pDC != NULL)
{
BMIH.biSize = sizeof(BITMAPINFOHEADER);
BMIH.biBitCount = 24;
BMIH.biPlanes = 1;
BMIH.biCompression = BI_RGB;
BMIH.biWidth = m_rcStaticWnd.Width();
BMIH.biHeight = m_rcStaticWnd.Height();
BMIH.biSizeImage = ((((BMIH.biWidth * BMIH.biBitCount) + 31) & ~31) >> 3) *
BMIH.biHeight;
m_hbStaticWnd = CreateDIBSection(pDC->GetSafeHdc(),
(CONST BITMAPINFO*)&BMIH, DIB_RGB_COLORS, (void**)&m_pbStaticWndBits, NULL, 0);
ReleaseDC(pDC);
}
if((m_hbStaticWnd == NULL) || (m_pbStaticWndBits == NULL))
{
AfxMessageBox(_T("BITMAP_NOT_CREATED_ERROR_MESSAGE"), MB_OK | MB_ICONSTOP);
CWnd *pWnd;
pWnd = GetDlgItem(IDC_SAVE_BITMAP);
pWnd->ShowWindow(SW_HIDE);
}
The PreTranslateMessage()
function to prevent the framework from closing the Dialog you need to return TRUE
.
BOOL CTypeStaticDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN)
{
if(pMsg->wParam == VK_BACK)
{
OnBackspace();
return TRUE;
}
if(pMsg->wParam == VK_SPACE)
{
m_szLine += _T(" ");
return TRUE;
}
if(pMsg->wParam == VK_DELETE)
{
m_szLine = _T("");
GetCharTyped(0x00);
return TRUE;
}
}
if(pMsg->message == WM_CHAR)
{
if(pMsg != NULL)
{
int key = pMsg->wParam;
if(key > 32 && key < 127)
{
GetCharTyped(key);
}
}
}
return FALSE;
return CDialogEx::PreTranslateMessage(pMsg);
}
This is the function that enters the text into the static control.
Here, you can set the font size.
void CTypeStaticDlg::GetCharTyped(int key)
{
char code;
code = key;
m_szLine += code;
CFont *oldFont;
CRect rc;
CDC *pDC;
pDC = StaticWnd.GetDC();
oldFont = pDC->SelectObject(&m_autofont);
pDC->SetTextColor(m_color);
StaticWnd.GetClientRect(&rc);
pDC->FillSolidRect(&rc, RGB(135, 206, 250));
pDC->DrawText(m_szLine, &rc, DT_LEFT | DT_WORDBREAK);
pDC->SelectObject(&oldFont);
ReleaseDC(pDC);
}
Next, set the font for the static control.
If you want a different font, change its size, or color.
void CTypeStaticDlg::OnBnClickedSetFont()
{
m_autofont.GetFontFromDialog();
CString szFont;
szFont = m_autofont.ContractFont();
m_autofont.ExtractFont(szFont);
m_color = m_autofont.GetFontColor();
StaticWnd.SetFont(&m_autofont);
GetCharTyped(VK_UP);
}
This function prepares the image to be written into the bitmap.
void CTypeStaticDlg::Draw()
{
CDC* pDC = GetDC();
if(pDC != NULL)
{
CDC dcMem;
if(dcMem.CreateCompatibleDC(pDC) == TRUE)
{
HBITMAP hOldBitmap = (HBITMAP)SelectObject(dcMem.GetSafeHdc(), m_hbStaticWnd);
CFont *oldFont;
dcMem.FillSolidRect(0, 0, m_rcStaticWnd.Width(),
m_rcStaticWnd.Height(), RGB(135, 206, 250));
oldFont = dcMem.SelectObject(&m_autofont);
dcMem.SetTextColor(m_color);
dcMem.DrawText(m_szLine, &m_rcStaticWnd, DT_LEFT | DT_WORDBREAK);
dcMem.SelectObject(&oldFont);
BOOL bResult = BitBlt(pDC->GetSafeHdc(),
m_rcStaticWnd.left,
m_rcStaticWnd.top,
m_rcStaticWnd.Width(),
m_rcStaticWnd.Height(),
dcMem.GetSafeHdc(),
0,
0,
SRCCOPY);
SelectObject(dcMem.GetSafeHdc(), hOldBitmap);
}
ReleaseDC(pDC);
}
}
Now when the user clicks the Save button, we write the bitmap data into the bitmap.
void CTypeStaticDlg::OnBnClickedSaveBitmap()
{
Draw();
CString szFilter;
szFilter = _T("Windows Bitmap Files
(*.bmp)|*.bmp|Device Independant Bitmap(*.dib)|*.dib||");
CFileDialog dlg(FALSE, DEFAULT_BITMAP_FILE_EXTENSION, DEFAULT_BITMAP_FILE_NAME,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter, NULL);
if(dlg.DoModal() == IDOK)
{
CString szPathName = dlg.GetPathName();
errno_t err;
FILE *pFile;
err = fopen_s(&pFile, szPathName, "wb");
if(pFile == NULL)
{
AfxMessageBox(_T("FILE_CREATE_ERROR_MESSAGE"));
return;
}
BITMAPFILEHEADER bmfh;
int nBitsOffset = sizeof(BITMAPFILEHEADER) + BMIH.biSize;
LONG lImageSize = BMIH.biSizeImage;
LONG lFileSize = nBitsOffset + lImageSize;
bmfh.bfType = 'B'+('M'<<8);
bmfh.bfOffBits = nBitsOffset;
bmfh.bfSize = lFileSize;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
UINT nWrittenFileHeaderSize = fwrite(&bmfh, 1, sizeof(BITMAPFILEHEADER), pFile);
UINT nWrittenInfoHeaderSize = fwrite(&BMIH, 1, sizeof(BITMAPINFOHEADER), pFile);
UINT nWrittenDIBDataSize = fwrite(m_pbStaticWndBits, 1, lImageSize, pFile);
fclose(pFile);
SetDlgItemText(IDC_STATIC_SAVE, _T("Saved"));
}
}
History
- 21st March, 2022: Initial version