 |
|
|
 |
|
 |
I have now used this for the 2nd time and once again it performed magnificantly. A really useful and reliable class. Thanks.
Mike Dear NYT - the fact is, the founding fathers hung traitors. Vincent Reynolds: My opposition is as enlightened as your support, jackass. dennisd45: My view of the world is slightly more nuanced dennisd45 (the NAMBLA supporter) wrote: I know exactly what it means. So shut up you mother killing baby raper.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
PJ,
When I run your demo app on my system instead of your image having a transparent background it has red cross-hatched lines. (when i click the "transparent" button of course)
Do you have any idea what could be causing this?
im using VS2003.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
No bug. If you look in CPJAImage_demoDlg::OnPaint() you will see I fill the background of the picture with a red cross hatch brush. I just did not update the image included with the article the last time I updated the code.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" - mYkel - 21 Jun '04
"There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05
Within you lies the power for good - Use it!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
sorry to bug you PJ - its a great class, but I have a question. I notice your example uses a Picture control to provide the co-ordinates/CRect/DC to draw the bitmap onto (Ive never done much with drawing, so I hope Im using the correct words) ..
I did this using a Picture control, and it works well - the only issue is the Picture control has a border I cant get rid of - ideally I'd like to use a Static for the 'placeholder' and get its DC .. but I seem to get unhandled exceptions when I replace the Picture control with a Static control ..
Is there anything obvious about using a Static that I should be aware of ? - or perhaps I made a simpler mistake - I guess I'll go over it again and see what I can find ...
[Edited after a play in my lunch-break] I think Ive found the answer - I think its the 'Frame' option I have set for the CPicture Property - I'll get to test it tonight ..... sorry if Ive messed you around
Thanks anyway, Garth
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You can use a static control for the drawing. Just derive a class from CStatic and overide it's OnPaint member function. I used a frame control in the demo because I wanted to keep all the drawing code in the dialog class. It saved me from having to pass all the drawing info from the button clicks to a seperate CStatic class.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" - mYkel - 21 Jun '04
"There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05
Within you lies the power for good - Use it!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
allmost 6 !!
thanks you vary much.
I have no imidiate work for your class, but i have been able to isolate the very much needed code to create this: HICON CreateGrayscaleIcon(HICON hIcon);
thanks a million.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You are very welcome
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" - mYkel - 21 Jun '04
"There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05
Within you lies the power for good - Use it!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi PJ,
in short I want to convert a 32bpp (RGBA) icon to grayscale while runtime without losing the alpha channel. If I drop such an icon into your test app and convert it to grayscale the alpha channel gets lost.
Taking a short look into your code shows that you make at last a RGB copy operation of the grayed pixels. The alpha channel is not set and so the formerly transparent parts become opaque.
Is there a way to convert 32bpp icons to grayscale without losing the alpha channel AND without using GDI+? I have code for doing this with GDI+ but I cannot use it yet in my project.
Thanks in advance!
Regards, mykel
If they give you lined paper, write the other way!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
After some nightly debugging I happily fixed the problem 
The following part of CPJAImage::GrayScale() causes the problem:
int nGray = Gray(GetBValue(*dst), GetGValue(*dst), GetRValue(*dst)); *dst = (DWORD)RGB(nGray, nGray, nGray); // *** this kills the alpha channel *** //
The RGB macro fills bit 0-24 with (BYTE)nGray. Bit 25-32 are filled with zeros and afterwards copied back into dst. So at this point the formerly alpha channel byte gets zero which is opaque.
Here is my fix:
Add the following macro at the top of pjaimage.h:
#define RGBA(r,g,b,a) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))|(((DWORD)(BYTE)(a))<<24)) This macro is similar to the RGB macro but it also accepts an alpha channel byte.
So everything is fine if we do:
int nGray = Gray(GetBValue(*dst), GetGValue(*dst), GetRValue(*dst)); BYTE* pAlpha = ((BYTE*)dst)+3; *dst = (DWORD)RGBA(nGray, nGray, nGray, *pAlpha);
That's all. Grayscaling a 32bpp icon doesn't kill the alpha channel anymore. Hope you like it!
Regards, mykel
If they give you lined paper, write the other way!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thanks Mykel.
Having others contribute bug fixes to bugs that the authors miss is part of what makes CP so great.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it! Honoured as one of The Most Helpful Members of 2004
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Mykel, not that it really matters, but I changed the code to*dst = (*dst & 0xff000000) | ((DWORD)RGB(nGray, nGray, nGray) & 0x00ffffff); Saves having to add the RGBA macro to the file.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it! Honoured as one of The Most Helpful Members of 2004
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi PJ,
sounds good to me.
I also forgot to thank you for another nice class! 
Have a nice day, mykel
If they give you lined paper, write the other way!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi,
First all thanks for the class. I found it quite handy drawing images transparently. I am using it in our latest project at work, but have come across a problem.
There seems to be some confusion (or my lack of understand) over the use w and h parameter of the DrawImage function, which lead to what I suspect to be the weird artifacts generated of drawing two images on the same DC.
What I have tried to do is draw two transparent images adjacently on my view. I have read that there was fix to a similar (or maybe the same) problem in 2003. I have in my code something like this...
CPJAImage img1; CPJAImage img2;
img1.SetImage(...); img2.SetImage(...);
// Note I treat w and h as logical offset of x and y respectively not as the width and height of the rect.
CSize img1Size = img1.GetSize(); CSize img2Size = img2.GetSize();
CPoint offset(10,10); // For example
img1.DrawImage(pDC, offset.x, offset.y, offset.x + img1Size.cx, offset.y + img1Size.cy, CPJA_TRANSPARENT); img2.DrawImage(pDC, offset.x + img1Size.cx, offset.y + img1Size.cy, offset.x + img1Size.cx + img2Size.cx, offset.y + img1Size.cy + img2Size.cy, CPJA_TRANSPARENT);
// This produces strange artifacts when my view is resized. // So I changed the code in these places to make it work. // In the DrawImage function.
//old BackGroundBitmap.CreateCompatibleBitmap(pDC, w, h); ... BackGroundDC.BitBlt(0, 0, w, h, pDC, x, y, SRCCOPY); ... TransparentDC.BitBlt(0, 0, w, h, &BackGroundDC, left, top, SRCCOPY);
//new changes BackGroundBitmap.CreateCompatibleBitmap(pDC, width, height); ... BackGroundDC.BitBlt(0, 0, width, height, pDC, x, y, SRCCOPY); ... TransparentDC.BitBlt(0, 0, width, height, &BackGroundDC, 0, 0, SRCCOPY);
Im not sure how these changes adversely affects the rest of the code. I have also added my own function to load a picture by a file name. I can post it if anyone wants it.
Thanks, Samson
Coding Monkey
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
 |
Sawjai wrote: TransparentDC.BitBlt(0, 0, width, height, &BackGroundDC, 0, 0, SRCCOPY);
This seems to be the only fix that is necessary as the painting is clipped to the supplied rectancle if width and height are bigger than w and h.
Thanks for the bug fix
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it! Honoured as one of The Most Helpful Members of 2004
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi PJ Arends,
Oppps, I had a mistake in my DrawImage parameters that I posted.  I will update it now.
Cheers, Samson
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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(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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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(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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|