May 10, 2024, 11:47:58 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


GDI+

Started by LarryMc, May 13, 2009, 01:59:15 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

LarryMc

I've  had pretty good luck with using antialiasing and drawing hollow shapes and filling those shapes with solid brushes.

I've got a gradient line brush to work and fill a rectangle.

What I'm having a problem with is figureing out how to properly gradient fill a pie segment using gdi+.

Right now I'm thinking I'll have to create a path; add a pie segment to it then use the path fill functions.

Am I on the right track?

Is there a "easy" way to do it.(using gdi+)

Does anyone have a sample they would share on how to do it?
(that would save me an awful lot of trial and error)

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

Just found a problem I'd been fighting for a couple of hours.

When setting the colors of a pen in GDI+ the number is set up as

0xaarrggbb  where
aa is the alpha value
rr is the red value
gg is the green value
bb is the blue value

so 0xFFFF0000 would be solid red
    0xFF0000FF would be solid blue.

We use  RGB(r as INT, g as INT, b as INT) all the time in EB to set colors

so if we want red we put  RGB( 0xff, 0 , 0 )
and for blue  RGB( 0, 0 ,  0xff )

so if I want to pass a color from EB to GDI+ I do this.

uint myred = RGB( 0xff, 0 , 0 )
and in GDI+ to set the pen color I pass it this for a parameter:
0xFF000000 | myredto account for the alpha.

Pretty straight forward except for one thing:
The GDI+ pen will paint a blue line.

EB doesn't build the uint with the color values in the order we enter them.
Where in GDI+ the number is:
0xaarrggbb  the colors are reversed in EB:
0xbbggrr

Like I said, I should have already known that but it took a good while for it to dawn on me what was happening.

And it doesn't mean there is anything wrong with EB.

It just means there has to be an adjustment made when passing colors between the two.

Larry

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ficko

Hi Larry,

There is a Methode -MakeARGB- in class CColor defined in "GdiPlusColor.inc".

I can't make it properly compiled - without errors- using Sapearos headers.

May he can give a tip how to do it.

Regards,
Ficko

sapero

typedef ARGB UINT

sub MakeARGB(char a,char r,char g, char b),ARGB
return b | (g << 8) | (r << 16) | (a << 24)
endsub


Ficko, the classes you see in gdiplus headers are just raw C++.

Ficko

Thanks Sapero I just didn't sleep too much last night :-[ -cheap excuse  :D-

By the way you brought me on an Idea.

What you think would be a big job -and worty- to include calling gcc in compilation process if the main compiler encounter C++ code ? :-\

Or is there more to it to simple genarate an object file and link it with?

Should I put it on Pauls wish list or is it stupid? ::)

I mean it would not be bad to have a little mixed language support wouldn't it? ;D

Ionic Wind Support Team

Ficko,
Not a stupid idea, just not a practical one.

object files are not compatible between different compilers, and we all use our own class method naming format (name mangling) so you would never get a link to work. In this case it wouldn't have helped you anyway, since it was a macro in a header file, which doesn't generate code but is replaced inline by the compiler.

Larry,
The 3D library already includes an RGBA function which works just as sapero's example.


Paul.
Ionic Wind Support Team

LarryMc

Quote from: Paul Turley on May 14, 2009, 10:21:32 AM
Larry,
The 3D library already includes an RGBA function which works just as sapero's example.

My designer uses the regular RGB function all over the place and passes that UINT value to my chart library.
So the 3D RGBA function doesn't do me any good.

I just made me a little function that takes the regular EB RGB UNIT ouput and an alpha value and gives me the proper value used by GDI+.

All is well in the world. ;)

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Larry,
It doesn't matter where the function comes from, the linker will just link in the necessary object.  All I was telling you is it is already built into Emergence by default and returns a UINT.

Paul.
Ionic Wind Support Team

LarryMc

And what I was saying is that at the point in time I need to make the conversion the individual r,g,b values aren't available to plug in to any function.

So the solution to MY problem was to make my own function that takes a single uint value and returns a single uint value. ;)

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

Was on a roll until I ran into this:
From the GDIPlusFlat.inc

declare import,GdipSetPathGradientBlend(pointer brush, _
            pointer blend,pointer positions, INT count),GpStatus

I know from the way all the other functions I've have worked with that:
brush has to be defined as a UINT ( where brush is created it is declared with" UINT brush byref")
blend and positions have to be arrays that contain numbers between 0 and 1.
count is either a 0 or a 1.
GpStatus is a int

I've declared and called it everyway I can think of and it(the function) keeps returning a "parameter invalid (2)" when I run it.
I know brush is correct because it paints like I expect it to.

Ficko/Sapero/Anyone

Got any ideas?

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

UINT brush byref

??

UINT brush = CreatePatternBrush(...
...
GdipSetPathGradientBlend(&brush,....

Paul.
Ionic Wind Support Team

sapero

Larry, do not refer to declarations in Ebasic include files, better search in your SDK/MSDN.
This is the original definition without 'const'
GpStatus WINGDIPAPI GdipSetPathGradientBlend(GpPathGradient *brush, REAL *blend, REAL *positions, INT count)
GpPathGradient is defined (typedef'ed) as a pointer.

GpPathGradient gradient
GdipCreatePathGradient(..., &gradient) ' create
GdipSetPathGradientBlend(gradient, ...) ' use

LarryMc

I still haven't been able to get the right combination.
AUTODEFINE "OFF"
$USE "GdiPlus.lib"
openconsole
declare import, GdiplusStartup(pointer token,pointer zinput,pointer output),int
declare import, GdiplusShutdown(pointer token)
declare import, GdipCreateFromHDC(uint hdc,graphics:pointer),INT
declare import, GdipCreatePen1(_color:UINT,width:FLOAT,unit:UINT,pen:pointer),INT
declare import, GdipSetSmoothingMode(graphics:pointer,SmoothingMode:UINT),INT
declare import, GdipDeletePen(pen:pointer),INT
declare import, GdipDeleteGraphics(graphics:pointer),INT
declare import, GdipDeleteBrush(pointer brush),int
declare import, GdipDrawPieI(pointer graphics,pointer pen, INT x, INT y, INT width, INT height, float startAngle, float sweepAngle),int
declare import, GdipCreatePath(int brushMode,pointer path),int
declare import, GdipAddPathPieI(pointer path, INT x, INT y, INT width, INT height, float startAngle, float sweepAngle),int
declare import, GdipDrawPath(pointer graphics,pointer pen,pointer path),int
declare import, GdipFillPath(pointer graphics,pointer brush,pointer path),int
declare import, GdipDeletePath(pointer path),int
declare import, GdipSetPathGradientCenterColor(pointer brush, uint colors),int
declare import, GdipCreatePathGradientFromPath(pointer path, pointer polyGradient),int
declare import, GdipSetPathGradientCenterPointI(pointer brush, point points),int
declare import, GdipSetPathGradientBlend(pointer brush, pointer blend ,pointer positions, INT count),int

' ------------------------------------------------------------
type GdiplusStartupInput
uint GdiplusVersion             ' Must be 1
pointer DebugEventCallback
int SuppressBackgroundThread
int SuppressExternalCodecs
endtype

$define SmoothingModeAntiAlias 4
$define FillModeAlternate 0
$define UnitPixel        2

   uint token
   GdiplusStartupInput StartupInputCLM

$MAIN
uint Hdc
pointer pBrush,lineGradient,pPath,pGraphics,pPen
window MainW
   ' Initialize GDI+

StartupInputCLM.GdiplusVersion = 1
if GdiplusStartup(token, StartupInputCLM, NULL)
MessageBOX 0,"Error initializing GDI+/nCan not proceed.","Fatal Error"
end
endif

OPENWINDOW MainW,0,0,900,650,@SIZE|@NOAUTODRAW,0,"Window",&main

WAITUNTIL MainW = 0
closeconsole
END

SUB main
SELECT @MESSAGE
CASE @IDCLOSEWINDOW
' Shutdown GDI+
GdiplusShutdown( token)
CLOSEWINDOW MainW
closeconsole
CASE @IDPAINT
Hdc = GetHDC(MainW)
GdipCreateFromHDC(Hdc, &pGraphics)
GdipSetSmoothingMode(pGraphics,SmoothingModeAntiAlias)

GdipCreatePath(FillModeAlternate,&pPath)
GdipAddPathPieI( pPath, 10, 10, 400, 400, 0.0, -45.0)

print GdipCreatePathGradientFromPath(pPath, &pBrush)
GdipSetPathGradientCenterColor(pbrush, 0xFFFF0000)
point pt1
pt1.x=210 :pt1.y=210
GdipSetPathGradientCenterPointI(pbrush, pt1)

float blend[2]
blend[0]=0.25
blend[1]=1.0

float positions[2]
positions[0]=.25
positions[1]=.75
int dummy=0

if GdipSetPathGradientBlend(pbrush, blend,positions, dummy)
MessageBOX mainw,"GdipSetPathGradientBlend failed","Error"
endif

GdipFillPath(pgraphics,pbrush,ppath)

int dw=1
GdipCreatePen1(0xFF000000,dw,UnitPixel,&pPen)
GdipDrawPath(pgraphics,pPen,pPath)

if pPath then print GdipDeletePath(pPath)
if pPen then print GdipDeletePen(pPen)
IF pBrush THEN print GdipDeleteBrush(pBrush)
if pGraphics then GdipDeleteGraphics(pGraphics)
ReleaseHDC MainW,Hdc
ENDSELECT
ENDSUB



Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

May 15, 2009, 09:44:35 AM #13 Last Edit: May 15, 2009, 09:48:25 AM by sapero
Found four 'bad' lines:
declare import, GdiplusShutdown(uint/*FIX*/ token)
declare import, GdipSetPathGradientCenterPointI(pointer brush, pointer/*FIX*/ points),int
if GdiplusStartup(&token/*FIX*/, &StartupInputCLM/*FIX*/, NULL)
int dummy=1 /*FIX*/

I don't know why with dummy=1 it works and with dummy=0 or 2 does not. I've used gdi+ to load/save images and blur transparent captions only.

Ficko

The reason why dummy = 1 works because you have only two choices.

"dummy" is a element of the MatrixOrder enumeration that specifies the order of the multiplication.
"MatrixOrderPrepend" specifies that the rotation matrix is on the left, and "MatrixOrderAppend" specifies that the rotation matrix is on the right.

Regards,
Ficko

LarryMc

Now I'm crashing trying to use the last function I think I need.
I'm wanting to set the outer color to blue.

I've added this declare:declare import, GdipSetPathGradientSurroundColorsWithCount(pointer brush, uint _color, int count),int

and this call:
GdipSetPathGradientSurroundColorsWithCount(pbrush, 0xFF0000ff, 1)
It crashes trying to execute that function.

Larry

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

Where did you get this declaration from ;D The last parameter - count - should be a pointer to integer.

LarryMc

I'll never tell! ;D

I discovered that I had it wrong right before your posting.

I'm just not very good at converting from declarations on msdn to EB.

Thanks

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

Here's another opportunity for me to look stupid:

With the function GdipSetPathGradientSurroundColorsWithCount commented out I get the effect I want with a red center(I set) and the default white for the outter edge.
The desired effect is due to the GdipSetPathGradientFocusScales function.

If I uncomment the  GdipSetPathGradientSurroundColorsWithCount function in order to change the outter edge to blue I get that effect.

However, at the same time the GdipSetPathGradientFocusScales function quits working; like it is commented out.

I have found examples on the internet where those 2 functions are used together and are compatible.

Any ideas?

Larry

AUTODEFINE "OFF"
$USE "GdiPlus.lib"
openconsole
declare import, GdiplusStartup(pointer token,pointer zinput,pointer output),int
declare import, GdiplusShutdown(uint token)
declare import, GdipCreateFromHDC(uint hdc,graphics:pointer),INT
declare import, GdipCreatePen1(_color:UINT,width:FLOAT,unit:UINT,pen:pointer),INT
declare import, GdipSetSmoothingMode(graphics:pointer,SmoothingMode:UINT),INT
declare import, GdipDeletePen(pen:pointer),INT
declare import, GdipDeleteGraphics(graphics:pointer),INT
declare import, GdipDeleteBrush(pointer brush),int
declare import, GdipDrawPieI(pointer graphics,pointer pen, INT x, INT y, INT width, INT height, float startAngle, float sweepAngle),int
declare import, GdipCreatePath(int brushMode,pointer path),int
declare import, GdipAddPathPieI(pointer path, INT x, INT y, INT width, INT height, float startAngle, float sweepAngle),int
declare import, GdipDrawPath(pointer graphics,pointer pen,pointer path),int
declare import, GdipFillPath(pointer graphics,pointer brush,pointer path),int
declare import, GdipDeletePath(pointer path),int
declare import, GdipSetPathGradientCenterColor(pointer brush, uint colors),int
declare import, GdipCreatePathGradientFromPath(pointer path, pointer polyGradient),int
declare import, GdipSetPathGradientCenterPointI(pointer brush, pointer points),int
declare import, GdipSetPathGradientBlend(pointer brush, pointer blend ,pointer positions, pointer count),int
declare import, GdipSetPathGradientSurroundColorsWithCount(pointer brush, pointer _color, pointer count),int
declare import, GdipSetPathGradientFocusScales(pointer brush, float xScale, float yScale),int
' ------------------------------------------------------------
type GdiplusStartupInput
uint GdiplusVersion             ' Must be 1
pointer DebugEventCallback
int SuppressBackgroundThread
int SuppressExternalCodecs
endtype

$define SmoothingModeAntiAlias 4
$define FillModeAlternate 0
$define UnitPixel        2

   uint token
   GdiplusStartupInput StartupInputCLM

$MAIN
uint Hdc
pointer pBrush,lineGradient,pPath,pGraphics,pPen
window w1
   ' Initialize GDI+

StartupInputCLM.GdiplusVersion = 1
if GdiplusStartup(&token, &StartupInputCLM, NULL)
MessageBOX 0,"Error initializing GDI+/nCan not proceed.","Fatal Error"
end
endif

OPENWINDOW w1,0,0,900,650,@SIZE|@NOAUTODRAW,0,"Window",&main

WAITUNTIL w1 = 0
closeconsole
END

SUB main
SELECT @MESSAGE
CASE @IDCLOSEWINDOW
' Shutdown GDI+
GdiplusShutdown( token)
CLOSEWINDOW w1
closeconsole
CASE @IDPAINT
Hdc = GetHDC(w1)
GdipCreateFromHDC(Hdc, &pGraphics)
GdipSetSmoothingMode(pGraphics,SmoothingModeAntiAlias)

GdipCreatePath(FillModeAlternate,&pPath)
GdipAddPathPieI( pPath, 110, 110, 400, 400, 0.0, -45.0)

GdipCreatePathGradientFromPath(pPath, &pBrush)
GdipSetPathGradientCenterColor(pbrush, 0xFFff0000)
uint colr[2]
colr[0]=0xFFff0000
colr[1]=0xFF0000ff
int cnt=2
'GdipSetPathGradientSurroundColorsWithCount(pbrush, &colr[0], &cnt)
point pt1
pt1.x=310 :pt1.y=310
GdipSetPathGradientCenterPointI(pbrush, pt1)
GdipSetPathGradientFocusScales(pbrush, .9, .9)
GdipFillPath(pgraphics,pbrush,ppath)

int dw=2
GdipCreatePen1(0xFF000000,dw,UnitPixel,&pPen)
GdipDrawPath(pgraphics,pPen,pPath)

if pPath then print GdipDeletePath(pPath)
if pPen then print GdipDeletePen(pPen)
IF pBrush THEN print GdipDeleteBrush(pBrush)
if pGraphics then GdipDeleteGraphics(pGraphics)
ReleaseHDC w1,Hdc

ENDSELECT
ENDSUB

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

Just in case anyone was wondering why the big dummy was playing with GDI+.

This is what the pie charts will look like in the coming update to the Chart Designer and Library.

Thanks to Ficko and Sapero for their help.

And a big thanks goes out to Jose Rocca for some examples he posted on another forum in another language..
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

SnarlingSheep

I know that you aren't done Larry, but the line between Pink and Purple isn't ant-aliased?

LarryMc

The same routine draws all the pie segments and all the lines.
Therefore everything is inside of the function that turns on antialiasing.
From what I've seen sometimes with a line at a certain angle and with certain colors it appears like that.

I have no control over it.

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

SnarlingSheep


LarryMc

Me saying I have no control over it isn't 100% true.

If I change the line width to 2 pixels then it looks better from an anti-aliasing standpoint but the whole chart takes on a bold, in your face sort of look.  I opted for the more mellow, although not perfect, look.

Now, if I was a programming wiz then there might be a totally different programming approach that might not do that.

But a wiz I am not.


Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

LarryMc

SnarlingSheep

I went back in and made a compromise.
I changed the line width to 2 but then softened the effect by changing the color from black to a shade of grey.

Thanks for mentioning it in the first place..

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library