|
Hi PJ Arends,
Oppps, I had a mistake in my DrawImage parameters that I posted.
I will update it now.
Cheers,
Samson
|
|
|
|
|
I am new to VC++ (recently converted from Borland C++ Builder).
Does any one any suggestion/code example on how to make CPJAImage a Drag & Drop Control in VC++ 7.1? I want to replace Image control with CPJAImage. I want to load image during design time (Image property) and also a transparent property.
Len Richter
|
|
|
|
|
CPJAImage is not a windows control (It is not a wrapper around an HWND), so I would say just call CPJAImage::DrawImage() from your regular control's WM_PAINT handler. Or you can do as I did in the demo app, which does support drag 'n drop.
Sonork 100.11743 Chicken Little
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
Within you lies the power for good - Use it!
|
|
|
|
|
I did try using Onpaint but I am missing something because I am getting a black rectangle (ie. like iti si not coping the BMP image from the Image control). Here is my code. Do you see anything I am missing?
private: System::Void ImagePaint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e)
{CPJAImage PJAImage;
PictureBox *pPictureBox = dynamic_cast<picturebox *="">(sender);
// Get handle to device context.
HDC hDC = (HDC)e->Graphics->GetHdc().ToInt32();
CDC* pDC = CDC::FromHandle(hDC);
COLORREF clr = pDC->GetPixel(CPoint(0,0));
PJAImage.SetImage(hDC, PJAI_BITMAP);
PJAImage.SetTransparentColour(clr);//RGB(0,0,0));
/
CDC DC;
DC.CreateCompatibleDC(pDC);
int save = DC.SaveDC();
SelectObject(background);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, pPictureBox->Image->Width, pPictureBox->Image->Height);
DC.SelectObject(bmp);
PJAImage.DrawImage(&DC, 0, 0, pPictureBox->Image->Width, pPictureBox->Image->Height, PJAI_TRANSPARENT | PJAI_STRETCHED);
pDC->BitBlt(0, 0, pPictureBox->Image->Width, pPictureBox->Image->Height, &DC, 0, 0, SRCCOPY);
DC.RestoreDC(save);
DC.DeleteDC();
// Release handle to device context.
e->Graphics->ReleaseHdc(hDC);
//ReleaseDC(pDC);
}
Len
|
|
|
|
|
Len2020 wrote:
HDC hDC = (HDC)e->Graphics->GetHdc().ToInt32();
Len2020 wrote:
PJAImage.SetImage(hDC, PJAI_BITMAP);
Here is your problem, SetImage requires a HBITMAP or HICON as the first parameter, you are passing in a HDC as a HBITMAP.
Sonork 100.11743 Chicken Little
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
Within you lies the power for good - Use it!
|
|
|
|
|
PIA WROTE:
Here is your problem, SetImage requires a HBITMAP or HICON as the first parameter, you are passing in a HDC as a HBITMAP.
I still can not get this to work due to my lack on knowledge between GDI and GDI++. I have searched on the web to get an understanding on DC and HBITMAP by it is still fuzzy to me. The problem is the handle HBITMAP and trying to get it. I did use HBITMAP operator but I am still get a black box only. I am still missing something obvious. Could you by chance correct my code. I would really appreciate it.
private: System::Void ImagePaint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e)
{CPJAImage PJAImage;
PictureBox *pPictureBox = dynamic_cast<picturebox *="">(sender);
// Get handle to device context.
HDC hDC = (HDC)e->Graphics->GetHdc().ToInt32();
CDC *pCDCImage = CDC::FromHandle(hDC);
// Create an in-memory DC compatible with the display DC we're using to paint.
CDC cdcMemory;
cdcMemory.CreateCompatibleDC(pCDCImage);
int save = cdcMemory.SaveDC();
COLORREF clr = cdcMemory.GetPixel(CPoint(0,0));
CBitmap bmp;
bmp.CreateCompatibleBitmap(&cdcMemory, pPictureBox->Image->Width, pPictureBox->Image->Height);
// Select Bitmap into the new Memory DC.
cdcMemory.SelectObject(bmp);
PJAImage.SetImage(bmp.operator HBITMAP(), PJAI_BITMAP);
//PJAImage.SetTransparentColour(clr);//RGB(0,0,0));
PJAImage.DrawImage(&cdcMemory, 0, 0, pPictureBox->Image->Width, pPictureBox->Image->Height, PJAI_TRANSPARENT | PJAI_STRETCHED);
// Copy the bits from the in-memory DC into the on-screen DC to actually do the painting.
pCDCImage->BitBlt(0, 0, pPictureBox->Image->Width, pPictureBox->Image->Height, &cdcMemory, 0, 0, SRCCOPY);
cdcMemory.RestoreDC(save);
cdcMemory.DeleteDC();
// Release handle to device context.
e->Graphics->ReleaseHdc(hDC);
}
Regards,
Len Richter
|
|
|
|
|
Len2020 wrote:
private: System::Void ImagePaint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e)
{CPJAImage PJAImage;
PictureBox *pPictureBox = dynamic_cast(sender);
// Get handle to device context.
HDC hDC = (HDC)e->Graphics->GetHdc().ToInt32();
CDC *pCDCImage = CDC::FromHandle(hDC);
// Create an in-memory DC compatible with the display DC we're using to paint.
CDC cdcMemory;
cdcMemory.CreateCompatibleDC(pCDCImage);
int save = cdcMemory.SaveDC();
OK, everything looks good up to this point. But the cdcMemory device context will only have a 1 x 1 pixel monochrome bitmap selected into at this point.
Len2020 wrote:
COLORREF clr = cdcMemory.GetPixel(CPoint(0,0));
Because cdcMemory contains a monochrome bitmap, clr will be either black or white (probably black).
Len2020 wrote:
CBitmap bmp;
bmp.CreateCompatibleBitmap(&cdcMemory, pPictureBox->Image->Width, pPictureBox->Image->Height);
I would have used the original pCDCImage here instead of the cdcMemory as the cdcMemory is currently monochrome.
bmp.CreateCompatibleBitmap(pCDCImage, ...
Len2020 wrote:
// Select Bitmap into the new Memory DC.
cdcMemory.SelectObject(bmp);
PJAImage.SetImage(bmp.operator HBITMAP(), PJAI_BITMAP);
Your PJAImage object now contains a monchrome bitmap that is initialized with random data, probably just a black box.
Len2020 wrote:
//PJAImage.SetTransparentColour(clr);//RGB(0,0,0));
PJAImage.DrawImage(&cdcMemory, 0, 0, pPictureBox->Image->Width, pPictureBox->Image->Height, PJAI_TRANSPARENT | PJAI_STRETCHED);
Again, the cdcMemory still contains only a 1 x 1 pixel monochrome bitmap as it's drawing surface.
Len2020 wrote:
// Copy the bits from the in-memory DC into the on-screen DC to actually do the painting.
pCDCImage->BitBlt(0, 0, pPictureBox->Image->Width, pPictureBox->Image->Height, &cdcMemory, 0, 0, SRCCOPY);
cdcMemory.RestoreDC(save);
cdcMemory.DeleteDC();
// Release handle to device context.
e->Graphics->ReleaseHdc(hDC);
}
You are seeing a black box because that is what you are telling it to do.
That being said, I am wondering why you are trying to use this class in a .NET app? While it will certainly work, I would think you would be better off using the .NET runtime.
I do not know how you are initializing the Image property of the PictureBox object that you are using here, but System.Drawing.Image is the base class for System.Drawing.Bitmap , and the Bitmap class has a method MakeTransparent(Color) that you could use.
private: System::Void ImagePaint(System::Object * sender, System::Windows::Forms::PaintEventArgs * e)
{
PictureBox *pPictureBox = dynamic_cast< PictureBox * >(sender);
Bitmap *pBitmap = dynamic_cast< Bitmap * >(pPictureBox->Image);
pBitmap->MakeTransparent(pBitmap->GetPixel(0, 0));
e->Graphics->DrawImage(pBitmap, 0, 0);
}
Note: I do not do .NET, so this code is totally untested, but you should get the idea;)
Sonork 100.11743 Chicken Little
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
Within you lies the power for good - Use it!
|
|
|
|
|
Hi Pete.
The problem in using the .Net class example is the PictureBox. It does not support true transparent. What I mean is the Image is transprent but you still show the PictureBox control. Boralnd had a PictureBox but also just a Image control and basically that is what I want. In further thinking about it using OnPaint and your control will not work either because the PictureBox will still be shown. I can not find a way to make the the PictureBox transparent also. I tried Form->TransprentKey and set Control->BackColor but that also make the form underneath transparent and therfeore see the desktop. Man, I though M$ would had a simple drag & drop ImageControl. I do not know how to create my own because still newbie to VS 2003. Do you have and further suggestions?
Len
|
|
|
|
|
Pete I had an Idea of capturing the area underneath the paintbox (form and controls), saving it as bmp and placing it into picturebox->backgroundimage. However I can not get the capture routine to work. Save problem of black box. Do you have any code exple on how to do this?
Len
|
|
|
|
|
As I said before, I do not do .NET, but could you not skip the picture box control and draw your image directly onto the form?
I do not know, maybe you would get a better answer if you took your question over to the managed VC forum.
Sonork 100.11743 Chicken Little
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
Within you lies the power for good - Use it!
|
|
|
|
|
It only works when the background is a single color or I didn't use it correctly? Thanks.
|
|
|
|
|
I'm thinking you're using it wrong, but without seeing your code, I can't be sure.
Sonork 100.11743 Chicken Little
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
Within you lies the power for good - Use it!
|
|
|
|
|
Thanks for the quick reply, I really appreciate it.
Actually, I want to draw a bitmap on another bitmap.
I want the above bitmap has a transparent backgroup.
Do you think this code will work?
Thanks again!
|
|
|
|
|
Ok, you are correct. It does not work the way you want. The DrawImage function uses the brush that is currently selected into the supplied DC as the background for transparent images. I will try to fix this and get back to you. It should not take more than a couple days.
Sonork 100.11743 Chicken Little
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
Within you lies the power for good - Use it!
|
|
|
|
|
Hi,
Thank you for your article.
Just wanted to ask you if you know how ot generate a bitmap with text on it.
FOr example:
HDC=GetDC(NULL);
TextOut(hdc, 0, 0, "AAA", 3);
............................
Now I want this to be saved as a bitmap.
Thank you.
JJordan
|
|
|
|
|
You can save this text into bmp file using these lines:
HBITMAP hBmp;
HPALETTE hpal;
hBmp = CreateCompatibleBitmap(hDC, rect.right, rect.bottom);
SelectObject(hDC, hBmp);
Bitmap bmp(hBmp, hpal);
CLSID encoderClsid;
GetEncoderClsid(_T("image/bmp"), &encoderClsid); // you can save it in gif simple using "image/gif"
Status stat;
stat = bmp.Save(strFileName, &encoderClsid, NULL);
// That's all !
// My question: How can I save the text in gif with the background made transparent ?
// if you use "image/gif" encoder -> you can get a GF89A file, but I don't know how to set it's background as transparent one !
Cheers,
Mihai
|
|
|
|
|
Is there any way to draw part of an icon using your class? I published the following question here in the forum, haven't got any answer yet, and thought you might know the answer:
I have a Windows XP 48x48 icon with shadow, and I need to draw only part of this icon. The standard DrawIconEx function allows to draw only the whole icon. I figured there was one way of drawing parts of the icon by using function MaskBlt. However, I cannot get the proper drawing result. The best solution I’ve come up so far is the following function:
<br />
void DrawIcon(HDC dc, HICON hIcon, int x, int y, int cx, int cy)<br />
{<br />
HDC memDC = CreateCompatibleDC(dc);<br />
ICONINFO IconInfo;<br />
GetIconInfo(hIcon, &IconInfo);<br />
HGDIOBJ old = SelectObject(memDC, IconInfo.hbmColor);<br />
MaskBlt(dc, x, y, cx, cy, memDC, 0, 0, IconInfo.hbmMask, 0, 0, MAKEROP4(SRCINVERT, SRCCOPY));<br />
SelectObject(memDC, old);<br />
DeleteDC(memDC);<br />
}<br />
Body of the icon is drawn correctly, and the transparency is there too. The problem of this function is that when drawing shadows of the icon it draws just black dots instead. Experimenting with all possible combinations of parameters for macro MAKEROP4 didn’t bring any good result.
Regards,
Vitaly Tomilov
|
|
|
|
|
Seeing how DrawIconEx() draws the icon the way you want, I say use it, just clip the output to the size you want.
All you need to do is create a memory DC, select into it a memory bitmap of the correct size, BitBlt from the given DC to the memory DC to get the correct background, use DrawIconEx() to draw the icon onto the memory DC, and the BitBlt it back to the given DC.
void DrawIconEx2(HDC DC, int DestX, int DestY, int Width, int Height, HICON hIcon, int SrcX, int SrcY)
{
HDC MemDC = CreateCompatibleDC(DC);
int SavedMemDC = SaveDC(MemDC);
HBITMAP MemBmp = CreateCompatibleBitmap(DC, Width, Height);
SelectObject(MemDC, MemBmp);
BitBlt(MemDC, 0, 0, Width, Height, DC, DestX, DestY, SRCCOPY);
DrawIconEx(MemDC, -SrcX, -SrcY, hIcon, 0, 0, 0, NULL, DI_NORMAL);
BitBlt(DC, DestX, DestY, Width, Height, MemDC, 0, 0, SRCCOPY);
RestoreDC(MemDC, SavedMemDC);
DeleteObject(MemBmp);
DeleteDC(MemDC);
}
Sonork 100.11743 Chicken Little
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
Within you lies the power for good - Use it!
|
|
|
|
|
Thank you for your answer, PJ Arends
I knew about this way of drawing, but considered it too slow, especially when drawing many icons, i.e. arse-ways
Ok, here's the situation I’m in: I need to do a simple task of populating a rectangle with pictures. Only unlike normally using standard pictures for that i need to use icons. For the very bottom line and the right top line I will have to draw a set of cut icons, which can be totally up to ...a lot, say 200 (1280/(16x16 icon) = 80; 1024/(16x16 icon) = 64; i.e. 80+64 = 144 icons)
And I knew from the beginning that I was just doing something minor wrong with those masks, so I was wondering what exactly. MaskBlt has got to work here, and it will be much faster, i just need to figure out how.
Alternatively, I see I could use your method for my whole rectangle area.
Thanx again,
Regards,
Vitaly Tomilov
Professional tooltips for all development platforms Free on www.Tooltips.NET
|
|
|
|
|
Hi,
Does anyone know how to select a jpeg image into a memory DC for manipulation?
Please show the code. Thanks.
|
|
|
|
|
Hi,
Does anyone know how to select a jpeg image into a memory DC for manipulation?
Please show the code. Thanks.
|
|
|
|
|
I haven't looked closely to the code yet, but I ran the demo, and it is nice!
There is a problem with the greyscale choice: when you select it, it works fine, but any other operation shows a black image, it seems the greyscale transformation destroys the original image, or something.
Except for icons, but for these, greyscale doesn't work anyway.
Actually, greyscale seems to work only on the internal image, not on the dragged ones.
Thank you for sharing.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
|
|
|
|
|
Hi Philippe,
Thanks for the feedback. I'm sorry this is not working for you. It is working just fine for me. I have downloaded the demo project (just to make sure I am using the same version as you) and ran it (both debug and release) and everything is working. I would drag .jpg, .gif, .bmp, and .ico files onto the demo with no problems. If you could track down the bug and let me know what you find, I would greatly appreciate it.
Thanks.
ps. Just a thought, what system are you using? what is your colour depth settings? The grayscale algorithm creates a copy of the original image, then changes the colour table for images with 256 or less colours, or changes the bits for images with 16, 24, or 32 bits per pixel.
---
It may be that your sole purpose in life is simply to serve as a warning to others.
|
|
|
|
|
OK, I tested it on a Win98 machine (16bit color depth) and it works fine: switch back and forth between greyscale and other options, greyscale on dropped files, etc.
It doesn't work on my NT4 sp 5 (+IE4's Active Desktop shell) 16bit color depth.
I saw a similar problem on a NT4 sp 5 without AD, 16 colors (!), except of course that greyscale didn't work because of lack of enough palette entries. But the image didn't shown back.
Same on a NT machine in TrueColor.
Seems to be a problem with NT API
I will try and investigate further, as time permits.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
|
|
|
|
|
I like this demo a lot, concise code. Ive recently written an image class myself (no good posting it as it is a wrapper for ImageMan - a commercial product). However after seeing this, I might consider adding the same functionality to this class. Such as drawing tools, dynamic resizing, multiple image comparison. If I can produce a lighter, faster class with the same functionality I'll post it at a later date. Thanks for the class.
"Life begins at 140"
|
|
|
|
|