I need to display an 'Empty' Bitmap (all values zero for RGBA channels) in a dialog.
Rough code:
HWND img = ::GetDlgItem( hwnd_, 228 );
unsigned char* charFrame = new unsigned char[frame_height*frame_width*4];
HWND hImage = CreateWindow(L"STATIC", L"", WS_VISIBLE | WS_CHILD | SS_BITMAP,
0, 0, frame_width, frame_height, img, (HMENU)1,GetWindowInstance( hwnd_ ),0);
HBITMAP bmp1 = CreateBitmap(frame_width,frame_height,1,32,charFrame);
SendMessage(hImage, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) (HANDLE) bmp1);
DeleteObject((HBITMAP)bmp1);
In the above code, charFrame variable is an unsigned char * pointer which has all the values set to zero. hwnd_ is the window handle.
Upon executing the code snippet, the window to which the BITMAP is sent, is not displaying the alpha content of the image. It displays a black image(R G B=0 0 0).
Any help is appreciated.
Related
I'm trying to draw a bitmap into a section of a CDC. I load the bmp, BitBlt the CDC with the bitmap information and nothing shows up, this is my code:
CWnd* pWindow = GetParent()->GetDlgItem(IDC_DIAGRAM);
CClientDC windowDC(pWindow);
CDC* CDC = windowDC;
// I draw the graph and other objects I need here, everything works perfectly so far
HANDLE hBitMap = ::LoadImage(0, L"Diagram.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
CBitmap bmp;
bmp.Attach((HBITMAP)hBitMap);
// For testing purposes I tried drawing this bmp into a separate picture control with the bmp property turned on and it drew fine, So i know the data is loaded properly.
CDC->SelectObject(bmp);
// start Position = (0,0) , width = 500, height = 500, imageStartPos = (0,0)
CDC->BitBlt(0, 0, 500, 500, &CDC, 0, 0, SRCCOPY);
After the following code nothing shows up, what im expecting is:
_____________
| | |
| BMP | |
|_____| |
| |
| CDC |
| |
| |
______________
Is there any way to do this without having to stack picture controls on top of each other?
edit: Got it to work, the working code is:
CDC* CDC = windowDC;
CDC* bmDC;
CClientDC dc(this);
// Load bmp the same way as above
bmDC->SelectObject(bmp);
bmDC->CreateCompatibleDC(&dc);
CDC->BitBlt(0, 0, 500, 500, bmDC, 0, 0, SRCCOPY);
I'm trying to create an application in Win32 api with c++ and I want to make it FullScreen without any bar , i succeeded but i still have a problem in the background image. The image is repeated but i want it to be stretched. Have you any idea?
below part from the code :
int WINAPI WinMain (HINSTANCE cetteInstance, HINSTANCE precedenteInstance,
LPSTR lignesDeCommande, int modeDAffichage)
{
HWND fenetrePrincipale;
MSG message;
WNDCLASS classeFenetre;
instance = cetteInstance;
classeFenetre.style = 0;
classeFenetre.lpfnWndProc = procedureFenetrePrincipale;
classeFenetre.cbClsExtra = 0;
classeFenetre.cbWndExtra = 0;
classeFenetre.hInstance = NULL;
classeFenetre.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
classeFenetre.hCursor = LoadCursor(NULL, IDC_ARROW);
// classeFenetre.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
//classeFenetre.hbrBackground = CreatePatternBrush(LoadBitmap( instance, MAKEINTRESOURCE("images\Image1.bmp" ) ) );
HBITMAP hbmp = LoadBitmap(instance,MAKEINTRESOURCE(IDB_BITMAP1));
if(NULL == hbmp)
{
MessageBox(NULL,L"BitMap Loading Failed.",L"Error",MB_ICONEXCLAMATION | MB_OK);
}
else
{
HBRUSH hbr = CreatePatternBrush(hbmp);
if(NULL == hbr)
{
MessageBox(NULL,L"Brush Creation Failed.",L"Error",MB_ICONEXCLAMATION | MB_OK);
}
else
{
//StretchBlt();
HDC hdcMem = GetDC (NULL) ;
HDC wndHDC = GetDC (fenetrePrincipale) ;
StretchBlt(hdcMem, 0, 0, 800, 600, wndHDC, 0, 0, 1280, 1024, SRCCOPY);
classeFenetre.hbrBackground = hbr ;
}
}
classeFenetre.lpszMenuName = NULL;
classeFenetre.lpszClassName = L"classeF";
//fullscreen mode and delete minimize and max buttons
// On prévoit quand même le cas où ça échoue
if(!RegisterClass(&classeFenetre)) return FALSE;
//WS_OVERLAPPEDWINDOW
fenetrePrincipale = CreateWindow(L"classeF", L"Ma premiere fenetre winAPI !",WS_MAXIMIZE|WS_POPUP ,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 630,
NULL,
NULL,//LoadMenu(instance, L"ID_MENU"),
cetteInstance,
NULL);
if (!fenetrePrincipale) return FALSE;
//ShowWindow(fenetrePrincipale, modeDAffichage);
ShowWindow(fenetrePrincipale,SW_MAXIMIZE);
UpdateWindow(fenetrePrincipale);
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return message.wParam;
}
thanks
You haven't shown the exact code, but it appears that you load a bitmap, create a brush from it, and then set that brush as the brush for your window. Brushes would indeed lead to the repeating-image behavior you report. To get a stretched bitmap, you may skip any brush-related code. Instead, handle the WM_ERASEBKGND message sent to your window. In it, call StretchBlt to paint your bitmap onto the client area of your window. The HDC to paint to is given in the message's wParam argument.
Steps
1, CreateWindowEx to create the window
2, SetWindowPos to place your window on top of all windows and Fullscreen
3, On your windows's WindowProce handle WM_PAINT message
4, Load your bitmap
5, Create a memory dc using CreateCompatibleDC
6, Selet your bitmap into memory dc by calling SelectObject
7, Do the StretchBlt to your actual dc, using the prepared memory dc as the source, you should know the actual width and height of the bitmap for proper stretching
I'm extracting jumbo icons for any given path using IImageList and SHGetFileInfo. Once I have that, I then render the HICON into a HBITMAP using DrawIconEx for eventual rendering with GDI+ Bitmap and Graphics objects.
Now, this all works great, except that when I do the final rendering of the bitmap, the very left edge always has a black artifact on it. This is true for pretty much any icon I get, and is always the left edge.
Any ideas where the dark line could be coming from?
The code I'm using is roughly:
1. Extract Icon:
// Get the image list index of the icon
SHFILEINFO sfi;
if (!SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX)) return NULL;
// Get the jumbo image list
IImageList *piml;
if (FAILED(SHGetImageList(SHIL_JUMBO, IID_PPV_ARGS(&piml)))) return NULL;
// Extract an icon
HICON hicon;
piml->GetIcon(sfi.iIcon, ILD_SCALE|ILD_TRANSPARENT, &hicon);
return hicon;
2. Generate Bitmap
HDC hDC = GetDC(NULL);
HDC hMemDC = CreateCompatibleDC(hDC);
HBITMAP hMemBmp = CreateCompatibleBitmap(hDC, x, y);
HBITMAP hResultBmp = NULL;
HGDIOBJ hOrgBMP = SelectObject(hMemDC, hMemBmp);
HBRUSH hbr = CreateSolidBrush(bg);
RECT rr = { 0, 0, 256, 256 }; // jumbo icons
FillRect(hMemDC, &rr, hbr);
DeleteBrush(hbr);
DrawIconEx(hMemDC, 0, 0, hicon, size, size, 0, NULL, DI_NORMAL);
hResultBmp = hMemBmp;
hMemBmp = NULL;
SelectObject(hMemDC, hOrgBMP);
return hResultBitmap;
3. Render GDI+ Bitmap to "window bitmap":
Bitmap *b = ::New Bitmap(hResultBitmap, NULL);
Graphics graphics(hdc);
graphics.SetTextRenderingHint(TextRenderingHintClearTypeGridFit);
SolidBrush bgbrush(Color(255, 255, 255, 255));
Rect r(0, 0, hwnd_w, hwnd_h);
graphics.FillRectangle(&bgbrush, r);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
Rect r(5, 5, 128, 128);
graphics.DrawImage(dpd->image_to_draw, r);
Wow, I spent another while last night playing with it. It's the ILD_SCALE in IImageList::GetIcon.
Get rid of that and it all works perfectly fine again. Go figure …
1. Extract Icon:
// Get the image list index of the icon
SHFILEINFO sfi;
if (!SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX)) return NULL;
// Get the jumbo image list
IImageList *piml;
if (FAILED(SHGetImageList(SHIL_JUMBO, IID_PPV_ARGS(&piml)))) return NULL;
// Extract an icon
HICON hicon;
piml->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hicon);
return hicon;
I'm using Winapi and I'm stuck. Normally to load image into SS_BITMAP on Dialog I'm using
HBITMAP hImage = ( HBITMAP ) LoadImage( hInstance, L"D:\\foo.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
HWND hFrame = GetDlgItem( hWnd, IDC_IMAGE );
SendMessage(hFrame, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hImage);
but now I have different task. I need to put there image from buffer which contains binary data of image. I've used some code but I know its wrong SetBitmapBits( hImage, sizeof(image),image);. image is char array with data.
Then you can use
CreateDIBSection to create a bitmap memory structure
SetDIBits to fill it with your pixel data
This SO answer looks good to me.
I want to load a BitMap image in a pic box I created inside a window...picBoxDisp is created using following mechanism..
picBoxDisp = CreateWindow("STATIC", "image box",
WS_VISIBLE |WS_CHILD | SS_BITMAP |WS_TABSTOP | WS_BORDER,
50, 50, 250, 300, hwnd , (HMENU)10000, NULL, NULL);
Now Next I created a hBitmap object and loaded an image in to it...
hBitmap = (HBITMAP) LoadImage(NULL,szFileName,IMAGE_BITMAP,0,0,
LR_LOADFROMFILE| LR_DEFAULTSIZE);
SendMessage(picBoxDisp,STM_SETIMAGE,(WPARAM) IMAGE_BITMAP,(LPARAM) NULL);
//now assign the new image
//Create a compatible DC for the original size bitmap, for example originalMemDc.
HDC originalDC = GetDC((HWND)hBitmap);
HDC originalMemDC = CreateCompatibleDC(originalDC);
if(originalMemDC==NULL){
MessageBox(NULL,"Problem while creating DC.","Error",MB_OK);
}
//Select hBitmap into originalMemDc.
SelectObject(originalMemDC,hBitmap);
//Create a compatible DC for the resized bitmap, for example resizedMemDc.
HDC picBoxDC = GetDC(picBoxDisp);
HDC resizedMemDC = CreateCompatibleDC(picBoxDC);
//Create a compatible bitmap of the wanted size for the resized bitmap,
HBITMAP hResizedBitmap = CreateCompatibleBitmap(picBoxDC,250,300);
//Select hResizedBitmap into resizedMemDc.
SelectObject(resizedMemDC,hResizedBitmap);
//Stretch-blit from originalMemDc to resizedMemDc.
//BitBlt(resizedMemDC,0,0,250,300,originalMemDC,0,0,SRCCOPY);
BITMAP bmp_old,bmp_new;
GetObject(hBitmap,sizeof(bmp_old),&bmp_old);
GetObject(hResizedBitmap,sizeof(bmp_new),&bmp_new);
StretchBlt ( resizedMemDC,0,0,bmp_new.bmWidth,bmp_new.bmHeight,
originalMemDC,0,0,bmp_old.bmWidth,bmp_new.bmHeight,
SRCCOPY);
////De-select the bitmaps.
if((resizedMemDC==NULL)||(hResizedBitmap == NULL)) {
MessageBox(NULL,"Something is NULL","Error",MB_OK);
}
else
//Set hResizedBitmap as the label image with STM_SETIMAGE
SendMessage(picBoxDisp,STM_SETIMAGE, (WPARAM) IMAGE_BITMAP,(LPARAM) hResizedBitmap);
I just cant understand, why the above code is not working ?
Thanks in advance,
You misunderstood the STM_SETIMAGE usage. Do this:
hBitmap = (HBITMAP)::LoadImage(NULL, szFileName, IMAGE_BITMAP,
0, 0, LR_LOADFROMFILE| LR_DEFAULTSIZE);
if (hBitmap != NULL)
{
::SendMessage(picBoxDisp, STM_SETIMAGE,
(WPARAM)IMAGE_BITMAP, (LPARAM)hBitmap);
}
EDIT: If you want to resize the bitmap before setting it as the label image, then follow this scheme for the simplest possible way to do it (with sub-optimal quality in the resized image...):
Create a compatible DC for the original size bitmap, for example originalMemDc.
Select hBitmap into originalMemDc.
Create a compatible DC for the resized bitmap, for example resizedMemDc.
Create a compatible bitmap of the wanted size for the resized bitmap, for example hResizedBitmap.
Select hResizedBitmap into resizedMemDc.
Stretch-blit from originalMemDc to resizedMemDc.
De-select the bitmaps.
Set hResizedBitmap as the label image with STM_SETIMAGE
Should work!
The static control won't stretch the image to its size. You could use SS_CENTERIMAGE but it either clips or fills the empty space with the color of the top left pixel (see http://msdn.microsoft.com/en-US/library/b7w5x74z.aspx). You'd have to stretch the bitmap yourself before sending it to the static control.
You're trying to assign an image to a static control, so you don't need to draw the image but to set the image on it.
// set the image
HBITMAP hold = (HBITMAP)SendMessage(hpicBoxDc, STM_SETIMAGE, IMAGE_BITMAP, LPARAM(hBitmap));
// clear the old image
if(hold && hold != hBitmap)
DeleteObject(hold );