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
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
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
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++.
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
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.
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
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.
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
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
UINT brush byref
??
UINT brush = CreatePatternBrush(...
...
GdipSetPathGradientBlend(&brush,....
Paul.
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
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
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.
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
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
Where did you get this declaration from ;D The last parameter - count - should be a pointer to integer.
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
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
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..
I know that you aren't done Larry, but the line between Pink and Purple isn't ant-aliased?
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
Gotcha :)
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
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
:)