Thread View: borland.public.delphi.nativeapi.win32
30 messages
30 total messages
Started by Ian Boyd
Thu, 24 Jul 2008 20:08
How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Thu, 24 Jul 2008 20:08
Date: Thu, 24 Jul 2008 20:08
20 lines
1519 bytes
1519 bytes
i want to draw an icon using:
DrawIcon(dc, hIcon);
but i first need to know how big the icon (dimensions, not bytes) is.
i looked at GetIconInfo(), but that only gives me the location of the
hot-spot, the color, and the mask.
Really, i'm trying to write the function:
function CreateBitmapFromIcon(const icon: HICON): HBITMAP;
begin
//Step 2: ???
end;
i was going to create a 32bpp bitmap, select it into a memdc, use DrawIcon
to do the drawing (with alpha transparency support).
But i'm stuck at step 1: Create a bitmap.
Re: How to determine the dimensions of an HICON?
Author: Marc Rohloff [TeamB]
Date: Thu, 24 Jul 2008 20:34
Date: Thu, 24 Jul 2008 20:34
14 lines
1686 bytes
1686 bytes
On Thu, 24 Jul 2008 16:08:47 -0400, Ian Boyd wrote: > i looked at GetIconInfo(), but that only gives me the location of the > hot-spot, the color, and the mask. The color and masks are HBITMAPS, you should be able to pass one into GetBitmapDimensionsEx to get the size. You could also use the HBITMAPs to draw on your canvas if necessary. Don;'t forget that the color bitmap is optional for black and white icons and that you need to delete the bitmaps when you are done. -- Marc Rohloff [TeamB] marc -at- marc rohloff -dot- com
Re: How to determine the dimensions of an HICON?
Author: Pieter Zijlstra
Date: Thu, 24 Jul 2008 21:41
Date: Thu, 24 Jul 2008 21:41
28 lines
1656 bytes
1656 bytes
Ian Boyd wrote: > i want to draw an icon using: > > DrawIcon(dc, hIcon); > > but i first need to know how big the icon (dimensions, not bytes) is. > > i looked at GetIconInfo(), but that only gives me the location of the > hot-spot, the color, and the mask. > > Really, i'm trying to write the function: > > function CreateBitmapFromIcon(const icon: HICON): HBITMAP; > begin > //Step 2: ??? > end; You can create a TIcon and use the HICON to set the handle of the just created Icon class, it should then be possible to retrieve the height and width of that Icon instance. If you do have the source have a look at Graphics.pas -> TIcon.SetHandle to see how that is done and you could come up with your own solution without using TIcon ... when still needed. -- Pieter
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Thu, 24 Jul 2008 23:26
Date: Thu, 24 Jul 2008 23:26
35 lines
1817 bytes
1817 bytes
> i want to draw an icon using:
>
> DrawIcon(dc, hIcon);
>
> but i first need to know how big the icon (dimensions, not bytes) is.
>
> i looked at GetIconInfo(), but that only gives me the location of the
> hot-spot, the color, and the mask.
Possibly not the most efficient way, but it works for me (including on
Vista when the icon on disk amounts to a single PNG entry):
function GetRealIconSize(Icon: HICON): TSize; overload;
var
Info: TIconInfo;
begin
if not GetIconInfo(Icon, Info) then RaiseLastOSError;
with TBitmap.Create do
try
Handle := Info.hbmMask;
Result.cx := Width;
Result.cy := Height;
finally
Free; //will destroy Info.hbmMask
end;
if Info.hbmColor = 0 then
Result.cy := Result.cy div 2
else
DeleteObject(Info.hbmColor);
end;
function GetRealIconSize(Icon: TIcon): TSize; overload;
begin
Result := GetRealIconSize(Icon.Handle);
end;
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Fri, 25 Jul 2008 20:10
Date: Fri, 25 Jul 2008 20:10
4 lines
1181 bytes
1181 bytes
Thanks guys, those were good suggestions. i even used the GDI+ version of the TIcon suggestion - ask the GDI+ object for the things width and height.
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Sat, 26 Jul 2008 19:29
Date: Sat, 26 Jul 2008 19:29
10 lines
1169 bytes
1169 bytes
> Really, i'm trying to write the function: > > function CreateBitmapFromIcon(const icon: HICON): HBITMAP; > begin > //Step 2: ??? > end; Out of curiosity, can I ask why? Also, are you wanting to convert icons that possibly already have an alpha channel, or only ones whose transparency is 'solid' (as was the case for all icons before XP)?
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Mon, 28 Jul 2008 13:51
Date: Mon, 28 Jul 2008 13:51
17 lines
1600 bytes
1600 bytes
>> Really, i'm trying to write the function: >> >> function CreateBitmapFromIcon(const icon: HICON): HBITMAP; >> begin >> //Step 2: ??? >> end; > > Out of curiosity, can I ask why? Also, are you wanting to convert > icons that possibly already have an alpha channel, or only ones whose > transparency is 'solid' (as was the case for all icons before XP)? Yes. i want to draw an HICON using GDI+. And while the Bitmap class of GDI+ does have a constructor that takes an HICON, it's doesn't handle partial transparency.
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Mon, 28 Jul 2008 17:08
Date: Mon, 28 Jul 2008 17:08
5 lines
1174 bytes
1174 bytes
> You can create a TIcon and use the HICON to set the handle of the just > created Icon class, it should then be possible to retrieve the height > and width of that Icon instance. It returns the wrong size (32 vs 48)
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Mon, 28 Jul 2008 17:25
Date: Mon, 28 Jul 2008 17:25
7 lines
1202 bytes
1202 bytes
>> i looked at GetIconInfo(), but that only gives me the location of the >> hot-spot, the color, and the mask. > > The color and masks are HBITMAPS, you should be able to pass one into > GetBitmapDimensionsEx to get the size. Nope. They both return 0,0.
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Mon, 28 Jul 2008 17:25
Date: Mon, 28 Jul 2008 17:25
18 lines
1692 bytes
1692 bytes
> > Out of curiosity, can I ask why? Also, are you wanting to convert > > icons that possibly already have an alpha channel, or only ones > > whose transparency is 'solid' (as was the case for all icons before > > XP)? > > Yes. > > i want to draw an HICON using GDI+. > > And while the Bitmap class of GDI+ does have a constructor that takes > an HICON, it's doesn't handle partial transparency. Ah, sounds tricky. I take it you've come across this in your Googling: http://msdn.microsoft.com/en-us/library/bb757020.aspx (or the blog entry from which it comes - http://preview.tinyurl.com/6bo5f7). I note the GDI version of their HICON to HBITMAP conversion uses Vista-only APIs (Begin/EndBufferedPaint), so the WIC version is in fact the more generic one (given the WIC stuff can be installed on XP).
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Mon, 28 Jul 2008 17:58
Date: Mon, 28 Jul 2008 17:58
6 lines
1284 bytes
1284 bytes
> I take it you've come across this in your Googling: > (given the WIC stuff can be installed on XP). i did. i kept on driving since i don't have WIC, and nobody else on XP would.
Re: How to determine the dimensions of an HICON?
Author: Marc Rohloff [TeamB]
Date: Mon, 28 Jul 2008 18:45
Date: Mon, 28 Jul 2008 18:45
10 lines
1515 bytes
1515 bytes
On Mon, 28 Jul 2008 13:25:09 -0400, Ian Boyd wrote: > Nope. They both return 0,0. What does your code look like? What version of Delphi are you using? -- Marc Rohloff [TeamB] marc -at- marc rohloff -dot- com
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Mon, 28 Jul 2008 19:17
Date: Mon, 28 Jul 2008 19:17
97 lines
3912 bytes
3912 bytes
>> Nope. They both return 0,0.
>
> What does your code look like?
> What version of Delphi are you using?
>> Nope. They both return 0,0.
>
> What does your code look like?
> What version of Delphi are you using?
function GetIconDimensions_DoesntWork(icon: HICON): TSize;
var
info: TIconInfo;
begin
{
This method doesn't work. Use GetIconDimenions instead.
You can't just construct a TIcon, give it the handle, and then call
Width and Height. It can (and usually will) return the wrong value
(e.g. 32 when it's really 48, and DrawIconEx(0,0) draws it 48)
}
if icon = 0 then
raise Exception.Create('GetIconDimensions: No icon handle
supplied');
Result.cx := 0; //for luck
Result.cy := 0; //and safety
Win32Check(GetIconInfo(icon, info));
try
if info.hbmColor <> 0 then
Win32Check(GetBitmapDimensionEx(info.hbmColor, Result))
else if info.hbmMask <> 0 then
Win32Check(GetBitmapDimensionEx(info.hbmMask, Result))
else
raise Exception.Create('GetIconDimensions: icon has no
bitmaps');
finally
DeleteObject(Info.hbmColor);
DeleteObject(Info.hbmMask);
end;
end;
Delphi 5. Doesn't matter too much, Chris Rolliston already discovered a
method that does work: give one of the bitmap handles returned by
GetIconInfo to a TBitmap and ask the VCL to figure out the width of the
HBITMAPs. The following works:
...happens to work
...on Windows XP
...service pack 2
...in 32-bit color mode
...today:
function GetIconDimensions(icon: HICON): TSize;
var
info: TIconInfo;
begin
{
You can't just construct a TIcon, give it the handle, and then call
Width and Height. It can (and usually will) return the wrong value
(e.g. 32 when it's really 48, and DrawIconEx(0,0) draws it 48)
You can't call GetBitmapDimensionEx on the bitmaps returned in
InfoInfo,
they both return zero.
But you can give the handle to those bitmaps to Delphi's TBitmap,
and
ask it to give you the width.
}
if icon = 0 then
raise Exception.Create('GetIconDimensions: No icon handle
supplied');
Win32Check(GetIconInfo(icon, info));
with TBitmap.Create do
try
Handle := Info.hbmMask;
Result.cx := Width;
Result.cy := Height;
finally
Free; //will destroy Info.hbmMask
end;
if Info.hbmColor = 0 then
Result.cy := Result.cy div 2
else
DeleteObject(Info.hbmColor);
end;
And no, the VCL doesn't call GetBitmapDimensionEx - it goes around the block
6 times first.
Re: How to determine the dimensions of an HICON?
Author: Marc Rohloff [TeamB]
Date: Mon, 28 Jul 2008 19:44
Date: Mon, 28 Jul 2008 19:44
13 lines
1757 bytes
1757 bytes
On Mon, 28 Jul 2008 15:17:37 -0400, Ian Boyd wrote: > Delphi 5. Doesn't matter too much, The implementation of TIcon is different in the latest version. Try replacing GetBitmapDimensionsEx with: var binfo:Windos.TBitmap; Win32Check( Windows.GetObject(info.hbmMask, sizeof(binfo), @binfo) ); result.cx := binfo.bmWidth; result.cy := binfo.bmHeight; -- Marc
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Mon, 28 Jul 2008 19:54
Date: Mon, 28 Jul 2008 19:54
60 lines
3023 bytes
3023 bytes
> Try replacing GetBitmapDimensionsEx with:
> var binfo:Windos.TBitmap;
> Win32Check( Windows.GetObject(info.hbmMask, sizeof(binfo), @binfo) );
> result.cx := binfo.bmWidth;
> result.cy := binfo.bmHeight;
i was just coming back to post that:
function GetIconDimensions(icon: HICON): TSize;
var
info: TIconInfo;
hbmp: HBITMAP;
bm: tagBITMAP;
begin
{
You can't just construct a TIcon, give it the handle, and then call
Width and Height. It can (and usually will) return the wrong value
(e.g. 32 when it's really 48, and DrawIconEx(0,0) draws it 48)
You can't call GetBitmapDimensionEx on the bitmaps returned in
InfoInfo,
they both return zero.
You *could* create a TBitmap and have the VCL figure it out.
But here's the actual working code that's faster,
and probably safer than using Borland code.
}
if icon = 0 then
raise Exception.Create('GetIconDimensions: No icon handle
supplied');
Result.cx := 0;
Result.cy := 0;
Win32Check(GetIconInfo(icon, info));
try
if info.hbmMask <> 0 then
hbmp := info.hbmMask
else if info.hbmColor <> 0 then
hbmp := info.hbmColor
else
raise Exception.Create('GetIconDimensions: icon has no
bitmaps');
if GetObject(hbmp, SizeOf(tagBITMAP), @bm) = 0 then
RaiseLastWin32Error;
Result.cx := bm.bmWidth;
Result.cy := bm.bmHeight;
finally
DeleteObject(Info.hbmColor);
DeleteObject(Info.hbmMask);
end;
end;
i'm still curious why Chris Rolliston divides the returned height by 2 when
there's no color mask. Is the height wrong in that case? Was that a bug in
Delphi's TIcon? Is GetObject () safe?
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Mon, 28 Jul 2008 19:55
Date: Mon, 28 Jul 2008 19:55
9 lines
1343 bytes
1343 bytes
> Possibly not the most efficient way, but it works for me (including on > Vista when the icon on disk amounts to a single PNG entry): > end; > if Info.hbmColor = 0 then > Result.cy := Result.cy div 2 Why do you think the height wrong by a factor of two if there's only a mask bitmap?
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Mon, 28 Jul 2008 20:00
Date: Mon, 28 Jul 2008 20:00
8 lines
1348 bytes
1348 bytes
> And no, the VCL doesn't call GetBitmapDimensionEx - it goes around > the block 6 times first. Just as well really - from MSDN: 'The GetBitmapDimensionEx function retrieves the dimensions of a compatible bitmap. The retrieved dimensions must have been set by the SetBitmapDimensionEx function.'
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Mon, 28 Jul 2008 20:07
Date: Mon, 28 Jul 2008 20:07
4 lines
1173 bytes
1173 bytes
> i'm still curious why Chris Rolliston divides the returned height by > 2 when there's no color mask. See my reply below.
Re: How to determine the dimensions of an HICON?
Author: Pieter Zijlstra
Date: Mon, 28 Jul 2008 20:22
Date: Mon, 28 Jul 2008 20:22
19 lines
1654 bytes
1654 bytes
Ian Boyd wrote: > i'm still curious why Chris Rolliston divides the returned height by > 2 when there's no color mask. Is the height wrong in that case? Was > that a bug in Delphi's TIcon? Is GetObject () safe? Probably in the assumption that when there is no color mask it concerns a black & white icon... From MSDN: hbmMask Specifies the icon bitmask bitmap. If this structure defines a black and white icon, this bitmask is formatted so that the upper half is the icon AND bitmask and the lower half is the icon XOR bitmask. Under this condition, the height should be an even multiple of two...[snipped] -- Pieter
Re: How to determine the dimensions of an HICON?
Author: Pieter Zijlstra
Date: Mon, 28 Jul 2008 20:25
Date: Mon, 28 Jul 2008 20:25
15 lines
1298 bytes
1298 bytes
Ian Boyd wrote: > > You can create a TIcon and use the HICON to set the handle of the > > just created Icon class, it should then be possible to retrieve the > > height and width of that Icon instance. > > It returns the wrong size (32 vs 48) Hmm strange, looks like it does not contain a hbmColor bitmap and it returns the system default for icon width & height. Is it a B&W icon? -- Pieter
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Mon, 28 Jul 2008 20:27
Date: Mon, 28 Jul 2008 20:27
12 lines
1404 bytes
1404 bytes
> > if Info.hbmColor = 0 then > > Result.cy := Result.cy div 2 > > Why do you think the height wrong by a factor of two if there's only > a mask bitmap? It's for the case of 'true' black and white (1 bit) icons - see the MSDN/SDK documentation for ICONINFO. Testing this, it seems the lack of a color bitmap and doubling up of the mask one only occurs with the icon has been loaded the WinAPI's LoadImage - use TIcon's LoadFromFile on exactly the same image and the quirk doesn't occur (to be clear, my code does work for both cases however).
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Mon, 28 Jul 2008 20:32
Date: Mon, 28 Jul 2008 20:32
10 lines
1417 bytes
1417 bytes
> But here's the actual working code that's faster, > and probably safer than using Borland code. 'Faster' (and so preferable) for sure, but hardly 'safer'... > i'm still curious why Chris Rolliston divides the returned height by > 2 when there's no color mask. Is the height wrong in that case? Was > that a bug in Delphi's TIcon? Is GetObject () safe? See my reply below.
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Mon, 28 Jul 2008 20:40
Date: Mon, 28 Jul 2008 20:40
12 lines
1524 bytes
1524 bytes
> > > You can create a TIcon and use the HICON to set the handle of the > > > just created Icon class, it should then be possible to retrieve > > > the height and width of that Icon instance. > > > > It returns the wrong size (32 vs 48) And a quick look at the VCL source (at least up to and including D2006) will show why... I think the reason for this behaviour (in the sense of 'why this is the case' rather than 'why this should be the case') is the limitations of the Win3.x API when it came to loading and drawing icons, Borland never updating the TIcon code once these limitations went away with Win32.
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Tue, 29 Jul 2008 01:40
Date: Tue, 29 Jul 2008 01:40
10 lines
1486 bytes
1486 bytes
> i want to draw an HICON using GDI+. > > And while the Bitmap class of GDI+ does have a constructor that takes > an HICON, it's doesn't handle partial transparency. Does your version of Delphi have GetDIBSizes and GetDIB available in Graphics.pas, or at least, are those routines copy and pasteable from Graphics.pas's implementation section? Also, when you say 'GDI+', do you mean the wrappers from www.progdigy.com? If your answers are all 'yes', then I think I may have a solution to your problem.
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Tue, 29 Jul 2008 13:51
Date: Tue, 29 Jul 2008 13:51
11 lines
1358 bytes
1358 bytes
> Is it a B&W icon? Nope. The icon i'm using is Adobe's 48x48 PDF icon. And Microsoft's 48x48 XPS Icon. And Windows Vista's 48x48 search icon And Windows media player's 48x48 movie icon. And...
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Tue, 29 Jul 2008 14:00
Date: Tue, 29 Jul 2008 14:00
13 lines
1512 bytes
1512 bytes
> Does your version of Delphi have GetDIBSizes Yes. > and GetDIB available in Graphics.pas Yes > Also, when you say 'GDI+', do > you mean the wrappers from www.progdigy.com? Yes. > If your answers are all 'yes', then I think I may have a solution to > your problem. Yes?
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Tue, 29 Jul 2008 14:25
Date: Tue, 29 Jul 2008 14:25
5 lines
1247 bytes
1247 bytes
> > If your answers are all 'yes', then I think I may have a solution to > > your problem. > Yes? Assuming that's not a command, see attachments...
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Tue, 29 Jul 2008 14:59
Date: Tue, 29 Jul 2008 14:59
13 lines
1576 bytes
1576 bytes
>> > If your answers are all 'yes', then I think I may have a solution to >> > your problem. >> Yes? > > Assuming that's not a command, see attachments... No, it was.....picture a dog with it's head cocked sideways.... "Yes?" That worked perfectly. i followed it up with a screenshot of before and after, with the working alpha transparency. Did you just bang that out now?
Re: How to determine the dimensions of an HICON?
Author: Ian Boyd
Date: Tue, 29 Jul 2008 15:15
Date: Tue, 29 Jul 2008 15:15
61 lines
2845 bytes
2845 bytes
Here's the final, gold, function call:
function GetIconDimensions(icon: HICON): TSize;
var
info: TIconInfo;
hbmp: HBITMAP;
bm: tagBITMAP;
begin
{
You can't just construct a TIcon, give it the handle, and then call
Width and Height. It can (and usually will) return the wrong value
(e.g. 32 when it's really 48, and DrawIconEx(0,0) draws it 48)
You can't call GetBitmapDimensionEx on the bitmaps returned in
InfoInfo,
they both return zero.
You *could* create a TBitmap and have the VCL figure it out.
But here's the actual working code.
}
if icon = 0 then
raise Exception.Create('GetIconDimensions: No icon handle
supplied');
Result.cx := 0;
Result.cy := 0;
//Get the color and mask bitmaps for the icon
Win32Check(GetIconInfo(icon, info));
try
//Pick either the mask or color bitmap to measure
if info.hbmMask <> 0 then
hbmp := info.hbmMask
else if info.hbmColor <> 0 then
hbmp := info.hbmColor
else
raise Exception.Create('GetIconDimensions: icon has no
bitmaps');
//Get info about the bitmap (like it's width and height)
if GetObject(hbmp, SizeOf(tagBITMAP), @bm) = 0 then
RaiseLastWin32Error;
Result.cx := bm.bmWidth;
Result.cy := bm.bmHeight;
{
If there is no color mask, then the black and white mask is 2x
high.
Top half is AND, lower half is XOR. See ICONINFO docs
}
if info.hbmColor = 0 then
Result.cy := Result.cy div 2;
finally
//Since we called GetInfoInfo, we must delete those two bitmaps
DeleteObject(Info.hbmColor);
DeleteObject(Info.hbmMask);
end;
end;
Re: How to determine the dimensions of an HICON?
Author: Chris Rolliston
Date: Tue, 29 Jul 2008 15:20
Date: Tue, 29 Jul 2008 15:20
6 lines
1361 bytes
1361 bytes
> Did you just bang that out now? Pretty much. Once you said GDI+ was the context, a Google search (can't remember what for exactly) came up with the two links I note at the top of the PAS file, with which I thought, should be simple enough...
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads