Can't Display Bitmap of Higher Resolution than CDC area - c++

Hi there dear gurus and expert coders.
i am not gonna start with im a newbie and don't know much about image programming but unfortunately those are the facts :(
I am trying to display an image from a bitmap pointer *ImageData which is of resolution
1392x1032. I am trying to draw that at an area of resolution or size 627x474.
However, repeated trying doesnt seem to work. It works when I change the bitmap image I created from *ImageData width and height to resolution or size of around 627x474
I really do not know how to solve this after trying all possible solutions from various forums and google.
pDC is a CDC* and memDC is a CDC initialized in an earlier method
Anything uninitialized here was initialized in other methods.
Here is my code dear humble gurus. Do provide me with guidance Yoda and Obi-Wan provided to Luke Skywalker.
void DemoControl::ShowImage( void *ImageData )
{
int Width; //Width of Image From Camera
int Height; //Height of Image From Camera
int m_DisplayWidth = 627 ;//width of rectangle area to display
int m_DisplayHeight = 474;//height of rectangle area to display
GetImageSize( &Width, &Height ) ; //this will return Width = 1392, Height 1032
CBitmap bitmap;
bitmap.CreateBitmap(Width,Height,32,1,ImageData);
CBitmap* pOldBitmap = memDC.SelectObject((CBitmap*)&bitmap);
pDC->BitBlt(22, 24, 627, 474, &memDC, 0, 0, SRCCOPY);
memDC.SelectObject((CBitmap*)pOldBitmap);
ReleaseDC(pDC);
}
Ok heres some additional parts
I think i should explain how the flow goes.
(a) A class (lets say DemoTestingDlg class) will pass the CDC as below to another class (lets say DemoControl class)
m_Demo = new DemoControl ;
m_Demo->Initialisation( this, this->GetDC() ) ;
(b) At the DemoControl class
bool DemoControl::Initialisation( CDemoTestingDlg m_FormControl, CDC m_StaticDisplay ) {
pDC = m_StaticDisplay ;
memDC.CreateCompatibleDC(pDC);
}
pDC and memDC is as such in the header:
CDC* pDC ; CDC memDC;
(c) If lets say an image is captured, the image pointer is passed to the DemoTestingDlg class which will subsequently call a showImage method in the Demo Control Class which is the method I wrote in the question. Am i doing it right?
Note: It did show an image if lets say they are of the same size (by they i mean the CDC and bitmap) so i was under the impression that my CDC pointer was passed correctly

StretchBlt is your friend :)
Edit: OK how do you get pDC? When is your function called? Form OnPaint or DrawItem?
This is a StretchBlt I do from a DrawItem call in an overriden CStatic.
HDC hBitmapDC = CreateCompatibleDC( pDrawItemStruct->hDC );
HBITMAP hBitmap = GetBitmap();
HGDIOBJ hOld = SelectObject( hBitmapDC, (HGDIOBJ)hBitmap );
StretchBlt( pDrawItemStruct->hDC, pDrawItemStruct->rcItem.left, pDrawItemStruct->rcItem.top, pDrawItemStruct->rcItem.right, pDrawItemStruct->rcItem.bottom,
hBitmapDC, 0, 0, 4, 4, SRCCOPY );
SelectObject( hBitmapDC, hOld );
DeleteObject( hBitmapDC );
Its not using the MFC classes to stretch a 4x4 bitmap into a larger space but works perfectly. My guess is that you aren't doing it in response to a WM_PAINT/WM_DRAWITEM and/or are using the wrong DC.
Edit re your edit: Do you then call DrawImage from inside an OnPaint or DrawItem call?
I would have thought you are better off not cacheing that CDC and passing the CDC in each time you wish to draw it.

"from a bitmap pointer *ImageData which is of resolution 1392x1032"
No it isn't, it's of size 1392x1032. Resolution is the amount of discrete visual units per distance.
Anyway as was mentioned above, you need to post more code. Show at least OnPaint(). Where are you instantiating the CPaintDC? Make a new project and put all your code in there, so that you have a minimal test set that exhibits the problem. You seem to be roughly on the right track, if you use StretchBlt() in place of the BitBlt() you're using now.

Related

Creating, displaying, and then accessing bitmap/DIB data (w/o GetBitmapBits())

I have inherited an old-school MFC Windows CE program, and am having to make some modifications to it. As part of this I have to create a monochrome image with text on it, and both display it on a screen as well as send each row of the image to a printer one at a time.
I originally used a bitmap, and had success using DrawText() and getting a test string (Hello World) to display on the screen (this code is in Figure 1). However, I hit a wall at the stage where I am looking to extract the wrap data from the bitmap. What I am trying to get is an array with 1s or 0s representing black or white. I had first thought I would use GetBitmapBits() but unfortunately the code I am working with is so old that function is not supported yet. I thought I could get around this issue by using GetBitmap() and then accessing the bmBits parameter. However this appears to always be null which was confirmed when I found the following link: Why does GetObject return an BITMAP with null bmBits?.
My next attempt was to follow the advice in the link and use CreateDIBSection() instead of CreateCompatibleBitmap(). This seems like the right path, and I should have access to the data I want, but unfortunately I cannot get the DIB to display (code is in Figure 2). I suspect I am doing something wrong in creating the header of the DIB, but I cannot figure out what my mistake is.
If anyone has suggestions for a way to access the data in the bitmap, or can see what I am doing wrong with the DIB, I would greatly appreciate the help!
*** FIGURE 1: Code to create and display a bitmap
void CRunPage::OnPaint()
{
CPaintDC dc(this); // property page device context for painting
CBitmap mBmp; // CBitmap object for displaying built-in bitmaps
CDC mDCMem; // CDC object to handle built-in bitmap
int iWidth, iHeight; // dimension to draw on the screen
int icurLabel, // current label index of open print file
iLabelNum; // number of labels in open print file
LPBITMAPINFOHEADER pBMIH; // bitmap header object for current label
LPBYTE pImage; // bitmap data for current label
CSize size; // size of label
int PreviewLeft,PreviewTop,PreviewWidth,PreviewHeight;
CRect Rect;
BITMAP bm;
LPVOID bmBits=NULL;
// Calculate the preview area
PreviewLeft=5;
PreviewTop=5;
GetDlgItem(IDC_RUN_NEXT)->GetWindowRect(&Rect);
ScreenToClient(&Rect);
PreviewWidth=Rect.left-PreviewLeft*2;
GetDlgItem(IDC_RUN_WRAPTEXT)->GetWindowRect(&Rect);
ScreenToClient(&Rect);
PreviewHeight=Rect.top-PreviewTop*2;
CRect textRect;
CString testText(_T("Hello World"));
CBitmap * pOldBitmap;
CBrush whiteBrush, *pOldBrush;
CPen blackPen, *pOldPen;
mDCMem.CreateCompatibleDC(&dc);
mBmp.CreateCompatibleBitmap(&dc, PreviewWidth+PreviewLeft*2, PreviewHeight+PreviewTop*2);
//mBmp.CreateCompatibleBitmap(&dc, PreviewWidth, PreviewHeight);
pOldBitmap = mDCMem.SelectObject(&mBmp);
blackPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
whiteBrush.CreateSolidBrush(RGB(255,255,255));
textRect.SetRect(0,0,PreviewWidth, PreviewHeight);
// this means behind the text will be a white box w/ a black boarder
pOldBrush = mDCMem.SelectObject(&whiteBrush);
pOldPen = mDCMem.SelectObject(&blackPen);
//these commands draw on the memory-only context (mDCMem)
mDCMem.Rectangle(&textRect);
mDCMem.DrawText((LPCTSTR)testText, 11, &textRect, DT_CENTER|DT_VCENTER);
mDCMem.SelectObject(pOldBrush);
mDCMem.SelectObject(pOldPen);
dc.StretchBlt(PreviewLeft,PreviewTop, PreviewWidth, PreviewHeight, & mDCMem, 0, 0, PreviewWidth, PreviewHeight, SRCCOPY);
mDCMem.SelectObject(pOldBitmap);
}
*** FIGURE 2: Trying to use a DIB instead of a bitmap
void CRunPage::OnPaint()
{
CPaintDC dc(this); // property page device context for painting
CBitmap mBmp; // CBitmap object for displaying built-in bitmaps
CDC mDCMem; // CDC object to handle built-in bitmap
int iWidth, iHeight; // dimension to draw on the screen
int icurLabel, // current label index of open print file
iLabelNum; // number of labels in open print file
LPBITMAPINFOHEADER pBMIH; // bitmap header object for current label
LPBYTE pImage; // bitmap data for current label
CSize size; // size of label
int PreviewLeft,PreviewTop,PreviewWidth,PreviewHeight;
CRect Rect;
BITMAP bm;
// Calculate the preview area
PreviewLeft=5;
PreviewTop=5;
GetDlgItem(IDC_RUN_NEXT)->GetWindowRect(&Rect);
ScreenToClient(&Rect);
PreviewWidth=Rect.left-PreviewLeft*2;
GetDlgItem(IDC_RUN_WRAPTEXT)->GetWindowRect(&Rect);
ScreenToClient(&Rect);
PreviewHeight=Rect.top-PreviewTop*2;
CRect textRect;
CString testText(_T("Hello World"));
CBitmap * pOldBitmap;
CBrush whiteBrush, *pOldBrush;
CPen blackPen, *pOldPen;
LPBYTE pFWandImageMem=NULL, pImageMem=NULL, pTemp=NULL;
int i=0,j=0, buffSize=0, numBytesPerRow=0, bitmapWidthPix,bitmapHeightPix;
char *numBytesPerRowString;
char temp;
void ** ppvBits;
BITMAPINFOHEADER bmif;
BITMAPINFO bmi;
HBITMAP myDIB, myOldDIB;
mDCMem.CreateCompatibleDC(&dc);
//this rect is the area in which I can draw (its x,y location is set by BitBlt or StretchBlt
//mBmp.CreateCompatibleBitmap(&dc, PreviewWidth+PreviewLeft*2, PreviewHeight+PreviewTop*2);
bmif.biSize = sizeof(BITMAPINFOHEADER);
bmif.biWidth = PreviewWidth+PreviewLeft*2;
bmif.biHeight = -(PreviewHeight+PreviewTop*2);//- means top down (I think? I tried both ways and neither worked)
bmif.biPlanes = 1;
bmif.biBitCount = 1;
bmif.biCompression = BI_RGB; // no compression
bmif.biSizeImage = 0; // Size (bytes) if image - this can be set to 0 for uncompressed images
bmif.biXPelsPerMeter = 0;
bmif.biYPelsPerMeter = 0;
bmif.biClrUsed =0;
bmif.biClrImportant = 0;
bmi.bmiColors[0].rgbBlue=0;
bmi.bmiColors[0].rgbGreen=0;
bmi.bmiColors[0].rgbRed=0;
bmi.bmiColors[0].rgbReserved=0;
bmi.bmiColors[1].rgbBlue=255;
bmi.bmiColors[1].rgbGreen=255;
bmi.bmiColors[1].rgbRed=255;
bmi.bmiColors[1].rgbReserved=0;
bmi.bmiHeader=bmif;
myDIB = CreateDIBSection(dc.GetSafeHdc(), &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0);
myOldDIB = (HBITMAP)mDCMem.SelectObject(myDIB);//SelectObject(mDCMem, myDIB);
blackPen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
whiteBrush.CreateSolidBrush(RGB(255,255,255));
textRect.SetRect(0,0,PreviewWidth, PreviewHeight);
// this means behind the text will be a white box w/ a black boarder
pOldBrush = mDCMem.SelectObject(&whiteBrush);
pOldPen = mDCMem.SelectObject(&blackPen);
//these commands draw on the memory-only context (mDCMem)
mDCMem.Rectangle(&textRect);
mDCMem.DrawText((LPCTSTR)testText, 11, &textRect, DT_CENTER|DT_VCENTER);
mDCMem.SelectObject(pOldBrush);
mDCMem.SelectObject(pOldPen);
dc.StretchBlt(PreviewLeft,PreviewTop, PreviewWidth, PreviewHeight, & mDCMem, 0, 0, PreviewWidth, PreviewHeight, SRCCOPY);
mDCMem.SelectObject(myOldDIB);
}
So I made two minor changes to the DIB code, and it is displaying the image correctly now.
First, I changed the way I passed in my pointer to the CreateDIBSection():
void ** ppvBits;
to
LPBYTE pBits;
And then I had to change how I passed that into CreateDIBSection. I also explicitly casted the return of CreateDIBSection() to an HBITMAP:
myDIB = CreateDIBSection(dc.GetSafeHdc(), &bmi, DIB_RGB_COLORS, (void**)&pBits, NULL, 0);
to
myDIB = (HBITMAP) CreateDIBSection(dc.GetSafeHdc(), &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0);
I have not had a chance to see if I can access the image data, but I am past the initial issues now. Thanks to anyone who looked at this, and if people know how to do the first (device dependent bitmap) method I would be interested to know.

Combine StretchBlt and TransparentBlt properly, so transparent bitmap can be created properly

INTRODUCTION AND RELEVANT INFORMATION:
Recently, I have asked, here in SO, a question about scaling a bitmap properly, so it can keep the quality of the picture:
Bitmap loses quality when stretched/shrinked on buttons background.
I have tried to employ a suggestion made in a comment, to use `StretchBlt, so I have made a small demo program.
It did improve the bitmaps sharpness, after I have set stretch mode to BLACKONWHITE.
I would like to try to make the portion of the bitmap, with the certain color-say black for example, transparent.
I have used TransparentBlt before, but I don't know how to do it now.
PROBLEM:
In order to preserve the sharpness of the picture, I need to StretchBlt it in the memory DC, with stretch mode being BLACKONWHITE.
The problem is that I do not know how to Blt it transparently into main window's DC.
Here is a code snippet from the demo app:
case WM_PAINT:
{
// main window's DC
hdc = BeginPaint(hWnd, &ps);
// main window's client rectangle
RECT r;
GetClientRect( hWnd, &r );
// memory DC for double buffering
HDC MemDC = CreateCompatibleDC( hdc );
// fill it with test brush
FillRect( MemDC, &r, (HBRUSH)GetStockObject( GRAY_BRUSH ) );
// select loaded bitmap into memory DC
HBITMAP old = (HBITMAP)SelectObject( MemDC, bmp );
// get bitmaps dimensions
BITMAP b;
GetObject( bmp, sizeof(BITMAP), &b );
// needed to preserve bitmap's sharpness
SetStretchBltMode( hdc, BLACKONWHITE );
StretchBlt( hdc, 0, 0, r.right - r.left, r.bottom - r.top,
MemDC, 0, 0, b.bmWidth, b.bmHeight, SRCCOPY );
/* TransparentBlt( ... ); call should go here,
so I can make portion of the bitmap transparent,
in order for the gray brush can be seen */
// cleanup
SelectObject( MemDC, old );
DeleteDC(MemDC);
EndPaint(hWnd, &ps);
}
return 0L;
break;
QUESTION:
How to modify the above code, so a bitmap can be transparent, in order for test brush to be seen ?
The original image is bellow.
I just need to use TransparentBlt( ..., RGB( 0, 0, 0 ) ); to make it transparent in black areas.
The example picture that shows result:
MY EFFORTS:
Browsing through Internet, I have found only simple tutorials, regarding double buffering.
I haven't found anything like this, but to be honest, I am inexperienced in WIN32 API, so I don't know how to phrase the question properly, in order to get better search results.
If further information is required, ask for it and I will supply it.
It is omitted to keep the question short.
You Need to create a mask use specific raster operations to copy only the Pixels were the mask is defined.
http://www.winprog.org/tutorial/transparency.html
The next code is MFC, but you can easily extract and convert the MFC objects into the Standard GDI operations.
http://www.codeproject.com/Articles/703/Drawing-Transparent-Bitmap-with-ease-with-on-the-f

Drawing multiple bitmaps on one Device Context in MFC - winapi

I want to use a single CDC, inwhich to draw 3 bitmaps, positioned in the CDC, and then pass it into UpdateLayeredWindow. My problem is that I can't get the SIZE* psize parameter of the UpdateLayeredWindow function right! Can Anyone help? What do I do?
BLENDFUNCTION bBlendFnc = {
AC_SRC_OVER,
0,
255,
AC_SRC_ALPHA
};
CBitmap btCdcBuff;
CBitmap* cache;
BITMAP hbCdcBuff;
btCdcBuff.CreateCompatibleBitmap(pCdcMain, szWndSize.cx, szWndSize.cy); btCdcBuff.GetBitmap(&hbCdcBuff);
cache = pCdcMain->SelectObject(&btCdcBuff); // pCdcMain is a compatible CDC with the screen (pCdcScreen)
Blend(&btIcon); // This function just creates a compatible CDC from a CPaintDC, selects the passed in CBitmap via SelectObject and AlphaBlends it to the pCdcMain.
pCdcMain->SelectObject(cache);
UpdateLayeredWindow(pCdcScreen, NULL, new CSize(hbCdcBuff.bmWidth, hbCdcBuff.bmHeight), pCdcMain, new CPoint(0, 0), 0, &bBlendFnc, ULW_ALPHA) // This fails and returns false
When using CreateCompatibleBitmap with UpdateLayeredWindow, make sure you pass in the CDC for the screen (ie, pCdcScreen not pCdcMain), so that the Bitmap created is of the correct format. See this thread: http://social.msdn.microsoft.com/Forums/en/windowsuidevelopment/thread/1fbcf5e4-b9eb-4537-bf0b-d330aa333fea

Unable to implement DIB printing with GDI (MFC)

MFC doc/view architecture, GDI drawing/printing. I have a DIB backbuffer I need to display and print.
After the long and painful road I came to the conclusion than I need to use DIB created with CreateDIBSection (rather than DDB created with CreateCompatibleBitmap), and I have to blit it onto printer dc with StretchDIBits (rather than StretchBlt).
But i'm not able to get this thing to work.
Here is what I do:
In my initialization routine, I setup the backbuffer, like this:
// Prepare device context:
CClientDC aDC(this);
OnPrepareDC(&aDC);
// Setup proper backbuffer:
_pMemDc = new CDC;
_pMemDc->CreateCompatibleDC(&aDC);
memset(&_bitmapInfo, 0, sizeof(BITMAPINFO));
_bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
_bitmapInfo.bmiHeader.biWidth = _sizeBackBuffer.cx;
_bitmapInfo.bmiHeader.biHeight = -_sizeBackBuffer.cy; // top-down
_bitmapInfo.bmiHeader.biPlanes = 1;
_bitmapInfo.bmiHeader.biBitCount = 24; // Maybe 32?
_bitmapInfo.bmiHeader.biCompression = BI_RGB;
HANDLE hMemBitmap = CreateDIBSection(aDC.GetSafeHdc(), &_bitmapInfo, DIB_RGB_COLORS, (void**)&_pBitmapRawBits, 0, 0);
_hOldSelBitmap = (HBITMAP)_pMemDc->SelectObject(hMemBitmap);
Variables with underscores are (private) member variables, declared like this:
CDC *_pMemDc; // Backbuffer memory dc
HBITMAP _hOldSelBitmap;
BITMAPINFO _bitmapInfo; // Backbuffer DIB (header-only)
unsigned char *_pBitmapRawBits; // Pointer to pixel data of DIB
SIZE _sizeBackBuffer; // Size of backbuffer, i.e. size of that DIB
Now below is what I do in my OnDraw override:
Firstly I get the area to be drawn like this (simplified code):
CRect rectClipBoxPlayground;
if (pDC->IsPrinting())
{
rectClipBoxPlayground = _printingParams.pPrintInfo->m_rectDraw;
}
else
{
pDC->GetClipBox(&rectClipBoxPlayground);
}
Then I calculate the corresponding rect coordinates in my backbuffer, which is usually (much) larger than the DC. Details of this calculation are irrelevant here, I just say that
CRect rectClipBoxBackBuffer;
represents the corresponding rect of backbuffer (in pixel coordinates of backbuffer).
Then I draw onto my backbuffer, using the _pMemDc memory dc.
And finally comes the part where I have troubles: blitting my DIB onto target dc (screen or printer). Here is what I do:
// Copy back buffer to screen/printer dc:
pDC->SetStretchBltMode(HALFTONE);
SetBrushOrgEx(pDC->GetSafeHdc(), 0, 0, 0);
// BELOW COMMENTED CODE OF StretchBlt WORKS(!) INSTEAD OF StretchDIBits.
//
//BOOL bSuccess = pDC->StretchBlt(rectClipBoxPlayground.left, rectClipBoxPlayground.top,
// rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(),
// _pMemDc, rectClipBoxBackBuffer.left, rectClipBoxBackBuffer.top,
// rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(), SRCCOPY);
HBITMAP hMemBitmap = (HBITMAP)_pMemDc->SelectObject(_hOldSelBitmap);
DWORD dwLines = StretchDIBits(pDC->GetSafeHdc(),
rectClipBoxPlayground.left, rectClipBoxPlayground.top, rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(),
rectClipBoxBackBuffer.left, rectClipBoxBackBuffer.top, rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(),
_pBitmapRawBits, &_bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
_pMemDc->SelectObject(hMemBitmap);
The problem is, the commented-out code of StretchBlt works flawlessly (except printing on some printers), but I can't use it because some printers have troubles with it. So I have to use StretchDIBits. Note that I firstly unselect the DIB from its memory dc temporarily, so that it is not associated with any dc. Then I use StretchDIBits but things just don't work! Output is messed up, like I give incorrect coordinates, areas are drawn off-set from where they should be drawn, and sometimes totally black. So I must be missing something (maybe something very trivial). Help! I tried changing signs of rectClipBoxBackBuffer.top and bitmapInfo.bmiHeader.biHeight, the results change, but nothing works like it should.
What am I doing wrong??
Dont't select the DIB into/out DC if you are going to use StretchDIBits.
DC can only contain DDB bitmap, if you supply a DIB, DC will convert it.
Microsoft's documentation about StretchDIBits is totally wrong. I found out that direction of Y axis has to be changed. Now following code works:
// Copy back buffer to screen dc:
pDC->SetStretchBltMode(HALFTONE);
SetBrushOrgEx(pDC->GetSafeHdc(), 0, 0, 0);
HBITMAP hMemBitmap = (HBITMAP)_pMemDc->SelectObject(_hOldSelBitmap);
DWORD dwLines = StretchDIBits(pDC->GetSafeHdc(),
rectClipBoxPlayground.left, rectClipBoxPlayground.top, rectClipBoxPlayground.Width(), rectClipBoxPlayground.Height(),
rectClipBoxBackBuffer.left, _sizeBackBuffer.cy - rectClipBoxBackBuffer.top - rectClipBoxBackBuffer.Height(), rectClipBoxBackBuffer.Width(), rectClipBoxBackBuffer.Height(),
_pBitmapRawBits, &_bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
_pMemDc->SelectObject(hMemBitmap);
P.S.: Now it works for screen drawing and print preview, but fails for actual printing, which was my original problem discussed here: How to print DIB backbuffer on printer - GDI, MFC

C++ GDI+ drawing text on a transparent layered window

(unmanaged C++)
I already succeeded drawing PNG files to a transparent layered window that I can drag around the desktop, but now my problem is drawing text on a transparent layered window
Here's my code and my attempt at drawing text in the middle, it's important to note that i'm using the screenDC instead of using the one in WM_PAINT messages
[edit]
updated code after the comments, now i'm just trying to write text on the bitmap before getting the HBITMAP version which i need to use
this time I'm using DrawString because textout() isn't GDI+, I hope DrawString really is GDI+ lol
still doesn't work though, wonder what i'm doing wrong
void Draw() // draws a frame on the layered window AND moves it based on x and y
{
HDC screenDC( NULL ); // grab screen
HDC sourceDC( CreateCompatibleDC(screenDC) );
POINT pos = {x,y}; // drawing location
POINT sourcePos = {0,0}; // top left of image
SIZE size = {100,100}; // 100x100 image
BLENDFUNCTION blendFunction = {0};
HBITMAP bufferBitmap = {0};
Bitmap* TheBitmap = crnimage; // crnimage was already loaded earlier
// ------------important part goes here, my attempt at drawing text ------------//
Gdiplus::Graphics Gx(TheBitmap);
// Font* myFont = new Font(sourceDC);
Font myFont(L"Arial", 16);
RectF therect;
therect.Height = 20;
therect.Width = 180;
therect.X = 0;
therect.Y = 0;
StringFormat format;
format.SetAlignment(StringAlignmentCenter);
format.GenericDefault();
Gdiplus::SolidBrush GxTextBrush(Gdiplus::Color(255, 255, 0,255));
WCHAR thetext[] = L"Sample Text";
int stats = Gx.DrawString(thetext, -1, &myFont, therect, &format, &GxTextBrush);
if(stats) // DrawString returns nonzero if there is an error
msgbox(stats);
stats = Gx.DrawRectangle(&Pen(Color::Red, 3), therect);
// the rectangle and text both draw fine now
// ------------important part goes here, my attempt at drawing text ------------//
TheBitmap->GetHBITMAP(0, &bufferBitmap);
HBITMAP oldBmpSelInDC;
oldBmpSelInDC = (HBITMAP)SelectObject(sourceDC, bufferBitmap);
// some alpha blending
blendFunction.BlendOp = AC_SRC_OVER;
blendFunction.SourceConstantAlpha = wndalpha;
blendFunction.AlphaFormat = AC_SRC_ALPHA;
COLORREF colorKey( RGB(255,0,255) );
DWORD flags( ULW_ALPHA);
UpdateLayeredWindow(hWnd, screenDC, &pos, & size, sourceDC, &sourcePos,
colorKey, &blendFunction, flags);
// release buffered image from memory
SelectObject(sourceDC, oldBmpSelInDC);
DeleteDC(sourceDC);
DeleteObject(bufferBitmap);
// finally release the screen
ReleaseDC(0, screenDC);
}
I've been trying to write text on my layered window for two days now, but from those attempts I know there are several ways I can go about doing this
(unfortunately I have no idea how exactly)
The usual option I see is drawing text on a bitmap, then rendering the bitmap itself
Use Gdi+ to load a bitmap
Create a Graphics object from the bitmap
Use DrawString to write text to the bitmap
Dispose of the Graphics object
Use the bitmap Save method to save the result to a file
Apparently one can also make a graphics object from a DC, then draw text on the DC, but again i have no clue as to how to do this
The overall approach looks right, but I think you've got some problems with the DrawString call. Check out the documentation (especially the sample) on MSDN.
Gx.DrawString(thetext, 4, NULL, therect, NULL, NULL)
The third, fifth, and sixth parameters (font, format, and brush) probably need to be specified. The documentation doesn't say that they are optional. Passing NULL for these is probably causing GDI+ to treat the call as a no-op.
The second parameter should not include the terminating L'\0' in the string. It's probably safest to use -1 if your string is always terminated.