Finding out max available print area - c#

I'm trying to find out max available area on my printer. I've printed a simple rectangle trying out different boundary variables. My question is, why doesn't first two work correctly? They don't print a full rectangle on the paper, only the left and top sides are drawn. Why does only the third one prints a full rectangle? I was under the impression of that all three should be working correctly. What am I missing?
Here's my code:
this.printDocument1.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0);
...
private void PrintPage(object sender, PrintPageEventArgs e)
{
//Method 1, no right and bottom sides are printed
e.Graphics.DrawRectangle(new Pen(Color.Black, 1), e.PageBounds);
//Method 2, same as Method 1
e.Graphics.DrawRectangle(new Pen(Color.Black, 1), e.MarginBounds);
//Method 3, works correctly
e.Graphics.DrawRectangle(new Pen(Color.Black, 1), new Rectangle((int)e.Graphics.VisibleClipBounds.X, (int)e.Graphics.VisibleClipBounds.Y, (int)e.Graphics.VisibleClipBounds.Width, (int)e.Graphics.VisibleClipBounds.Height));
}

First one doesn't work because you are trying to print out of margins. Second one fails because you are trying to print over the margin, so the right and bottom lines fall 1 pixel off the bounds. Now 3rd one works IMO because, printing rectangle coordinates are floating point, and you are casting them to integers, thus rounding them down, so the rectangle falls inside the print area.
EDIT
Some additional info I found regarding your comment:
"If the Graphics object is using a nondefault PageUnit,[2] then VisibleClipBounds will be in different units than PageBounds (which is always in units of 100 dpi). To handle these variables, it's useful to have a helper method to return the "real" page bounds in a consistent unit of measure"
Check out this article , I believe it covers everything.

My first guess is that 2 is working with the margins you set previously (0,0,0,0) and that your printer doesn't actually support no-margin printing (most don't). Because of the fact that most printers require at least some margins, #1 will pretty much never work.
Method 3 appears to actually be querying the driver for the printable area of the page and then using that, so, it works.
As for why you get the top and left instead of nothing with #1 and #2, this is because you're just saying "print me a rectangle of these dimensions starting at the upper left hand corner of the printable area" not "print me a rectangle with these dimensions and start in the far upper left hand corner of the page where you can't actually print" so it's trying to, but it goes off the edge of the page since it's bigger than the printable area of the page.

Related

Drawing an arrow with an outline

I'm trying to draw multiple arrows with a colored outline on a form, so far I'm using the following code:
Pen arrow_pen = new Pen(Color.FromArgb(r, g, b), 8);
arrow_pen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
GraphicsPath arrow = new GraphicsPath();
arrow.AddLine(
coordinates1,
coordinates2,
coordinates3,
coordinates4
);
obj.DrawPath(arrow_pen, arrow);
obj.FillPath(Brushes.White, arrow);
arrow.Dispose();
arrow_pen.Dispose();
It draws the outline for the arrow, but then it dosent fill the path with white (obj.FillPath does nothing), am I missing something or am I doing this the wrong way?
The documentation says:
Fills the interior of a GraphicsPath.
Your path is only a single line and not closed. Therefore, according to the documentation:
If the path represented by the path parameter is not closed, an additional segment is added from the last point to the first point to close the path.
So now you have two identical lines spanning an area of exactly nothing. That area is filled but you cannot see it, as it's zero pixels wide. You need to define a closed graph that has an area greater than zero to actually fill something.

C# String.Format and SpriteBatch.DrawString spacing issues

I have strings formatted using the code below
String.Format("{0,-10} {1,10}", "Kills:", kills);
String.Format("{0,-10} {1,10}", "Points:", points);
String.Format("{0,-10} {1,10}", "$:", currency);
From what I understood, the first part of the strings should be left justified with a 10 space buffer and then the integer variables should be printed right justified with a 10 space buffer.
However when attempt to draw the strings using SpriteBatch.DrawString, nothing aligns properly.
The left aligned side prints properly, but the right aligned side centres on a certain point, for example if kills = 50 and points = 5002, the 50 will be centered over the 00 in the 5002...
What is going on?
Quite simply, I suspect you're not using a monospaced font. When different characters have different widths, you can't use spaces to line things up. (Your sample works when using Console.WriteLine for example, as the console has a fixed width font by default.)
You'll either have to use a monospaced font, or you'll have to draw the strings separately - draw each string to fit the relevant area. I don't know anything about XNA, but I'd expect you to either have to measure the width of the string before you draw it (so you can subtract it from the right-hand edge, for example) or specify some sort of layout value which indicates "right-align this string with a particular point".
Most likely you draw the text with a proportional font. Bear in mind that characters don't have the same width, so you cannot align texts with spaces.
As I do not have reply privileges, (or some such thing, as there is no reply button for answers), but I would like to contribute, I will post this answer.
Jon's answer mentioned measuring the string, this is possible by spriteFont.MeasureString(string s);. This returns a Vector2, the X portion of which is the width of the rendered text. (Y is height, which could be helpful for other things) This allows you to use a font other than a monospace font.
Here is an example of using MeasureString:
I'm not really sure what the question is asking, but if you wanted a single line of text similar to "Kills:50 Points:5002" but width two different spritebatch calls you could do the following (note I typed this directly into stackoverflow, so there may be minor syntax errors):
float killStringWidth = spriteFont.MeasureString(killString).X;
spriteBatch.DrawString(spriteFont, killString, new Vector2(0,0), Color.White );
spriteBatch.DrawString(spriteFont, pointString, new Vector2(killStringWidth + 10, 0), Color.White );

How to find the actual printable area? (PrintDocument)

Why is finding out this magic Rectangle so difficult?
In the OnPrintPage event I have PrintPageEventArgs and I am trying to draw using the Graphics within the bounds of the maximum printable area.
I have tried using PageBounds, PrintableArea, Graphics.VisibleClipBounds, etc. All fail to consistently get the drawing area, especially when switching from Landscape to Portrait layout. PrintableArea does not seem to ever change when you switch from Landscape to Portrait.
I have also noticed that there is a difference in how Graphics.VisibleClipBounds is set depending on if I'm doing a print preview and an actual print. In a preview it always shows Portrait width/height, so I have to check if it is a preview and I have to manually swap the width/height when it is a Landscape.
I need an algorithm to calculate the printable area as it relates to the current Graphics context, not an arbitrary theoretical print area that isn't used in actual drawing.
My concern is dealing with the Graphics matrix offset. So far I have noticed severe inconsistencies between how the Graphics context is pre-translated using the hard margins depending on factors like:
If OriginAtMargins is true or false (not behaving as I would think)
If I'm printing to a printer, or using the PrintPreviewControl (I have to check if this is a print to preview or a print to page to handle the translation properly)
If I'm using my printer at home or my printer at work (both behave differently)
Is there a standard way to handle this? Should I just reset the matrix? When I set OriginAtMargins to true, the Graphics is pre-translated to 84,84, but my margins are 100,100. The hard margins are 16,16. Shouldn't it be translated to 100,100? Since 0,0 should be at the page bounds, not the hard margins.
Basically my method should always work at getting the best printable rectangle. I just need a consistent, device-independent way of making sure that my drawing origin (0, 0) is at the top-left of the page in order for the above Rectangle to be of any use to me.
Your question lacks a little clarity as to what the "best" rectangle is. I'm going to assume you mean the largest rectangle that will be 100% visible when printed.
So lets start by making sure we understand what the print document graphics object "origins" are and how the OriginAtMargins property affects this origin.
OriginAtMargins - Gets or sets a value indicating whether the position
of a graphics object associated with a page is located just inside the
user-specified margins or at the top-left corner of the printable area
of the page.
- PrintDocument Class Definition on MSDN
So with OriginAtMargins set to false (default) the graphics object will be adjusted to the PrintableArea rectangle (about 5/32 from each page edge for my laser printer, old laser printers may be more, new inkjets may print right to the edge, software PDF printers will print right to the edge). So 0,0 in my graphics object is actually 16,16 on the physical page of my laser printer (your printer may be different).
With the default 1 inch page margins and OriginAtMargins set to true, the graphics object will be adjusted to the 100,100,650,1100 rectangle for a normal portrait letter page. This is one inch inside each physical page edge. So 0,0 in your graphics object is actually 100,100 on the physical page.
Margins are also known as "soft margins" as they are defined in software and not affected by the physical printing device. This means they will be applied to the current page size in software and reflect the actual page dimension portrait or landscape.
PrintableArea is also known as "hard margins" which reflect the physical limitations of your printing device. This will vary from printer to printer, from manufacturer to manufacturer. Because these are hardware measurements, they do not rotate when you set the page to landscape/portrait. The physical limitations won't change on the printer regardless of software print settings, so we need to make sure we apply them on the correct axis depending on our software settings for the print document (orientation).
So following the rough model of the sample code you posted, here's a PrintDocument.PrintPage event handler that will draw a rectangle as large as possible while still being visible (with the default PrintDocument.OriginsAtMargins being false). If you set PrintDocument.OriginsAtMargins to true it will draw a rectangle as large as possible while still being visible inside the configured soft margins (defaults to 1" from page edges).
PrintAction printAction = PrintAction.PrintToFile;
private void printDocument_BeginPrint(object sender, PrintEventArgs e)
{
// Save our print action so we know if we are printing
// a preview or a real document.
printAction = e.PrintAction;
// Set some preferences, our method should print a box with any
// combination of these properties being true/false.
printDocument.OriginAtMargins = false; //true = soft margins, false = hard margins
printDocument.DefaultPageSettings.Landscape = false;
}
private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics g = e.Graphics;
// If you set printDocumet.OriginAtMargins to 'false' this event
// will print the largest rectangle your printer is physically
// capable of. This is often 1/8" - 1/4" from each page edge.
// ----------
// If you set printDocument.OriginAtMargins to 'false' this event
// will print the largest rectangle permitted by the currently
// configured page margins. By default the page margins are
// usually 1" from each page edge but can be configured by the end
// user or overridden in your code.
// (ex: printDocument.DefaultPageSettings.Margins)
// Grab a copy of our "soft margins" (configured printer settings)
// Defaults to 1 inch margins, but could be configured otherwise by
// the end user. You can also specify some default page margins in
// your printDocument.DefaultPageSetting properties.
RectangleF marginBounds = e.MarginBounds;
// Grab a copy of our "hard margins" (printer's capabilities)
// This varies between printer models. Software printers like
// CutePDF will have no "physical limitations" and so will return
// the full page size 850,1100 for a letter page size.
RectangleF printableArea = e.PageSettings.PrintableArea;
// If we are print to a print preview control, the origin won't have
// been automatically adjusted for the printer's physical limitations.
// So let's adjust the origin for preview to reflect the printer's
// hard margins.
if (printAction == PrintAction.PrintToPreview)
g.TranslateTransform(printableArea.X, printableArea.Y);
// Are we using soft margins or hard margins? Lets grab the correct
// width/height from either the soft/hard margin rectangles. The
// hard margins are usually a little wider than the soft margins.
// ----------
// Note: Margins are automatically applied to the rotated page size
// when the page is set to landscape, but physical hard margins are
// not (the printer is not physically rotating any mechanics inside,
// the paper still travels through the printer the same way. So we
// rotate in software for landscape)
int availableWidth = (int)Math.Floor(printDocument.OriginAtMargins
? marginBounds.Width
: (e.PageSettings.Landscape
? printableArea.Height
: printableArea.Width));
int availableHeight = (int)Math.Floor(printDocument.OriginAtMargins
? marginBounds.Height
: (e.PageSettings.Landscape
? printableArea.Width
: printableArea.Height));
// Draw our rectangle which will either be the soft margin rectangle
// or the hard margin (printer capabilities) rectangle.
// ----------
// Note: we adjust the width and height minus one as it is a zero,
// zero based co-ordinates system. This will put the rectangle just
// inside the available width and height.
g.DrawRectangle(Pens.Red, 0, 0, availableWidth - 1, availableHeight - 1);
}
The two lines that determine available width and available height are what I think you were looking for in your question. Those two lines take into account whether you want soft margins or hard margins and whether the print document is configured for landscape or portrait.
I used Math.Floor() for the easy way out to just drop anything past the decimal (ex: 817.96 -> 817) just to make sure the available width and height was just inside the available dimensions. I'm "failing safe" here, if you wanted to you could maintain float based co-ordinates (instead of int), just be careful to watch for rounding errors that will result in the clipped graphics (if it rounds 817.96 up to 818 and then the printer driver decides that's no longer visible).
I tested this procedure in both portrait and landscape with both hard margins and soft margins on a Dell 3115CN, a Samsung SCX-4x28 and CutePDF software printer. If this didn't adequately address your question, consider revising your question to clarify "magic rectangle" and "best rectangle".
EDIT: Notes About "Soft Margins"
Soft margins are applied in software and do not take into consideration the hardware limitations of the printer. This is intentional and by design. You can set the soft margins outside the printable area if you want and the output may be clipped by your printer's driver. If this is undesirable for your application, you need to adjust the margins in your program code. Either you can prevent the user from selecting margins outside the printable area (or warn them if they do) or you can enforce some min/max conditions in your code when you actually start printing (drawing) the document.
Example Case: If you set the page margins to 0,0,0,0 in Microsoft Word 2007 a warning dialog pops up that reads "One or more margins are set outside the printable area of the page. Choose the Fix button to increase the appropriate margins." If you click fix, Word will simply copy the hard margins into the soft margins, so the dialog now shows 0.16" for all margins (my laser printer's capabilities).
This is expected behavior. It is not a bug/problem with Microsoft Word if the printed page is clipped because the user ignored this warning and used 0,0,0,0 page margins. This is the same in your application. You need to enforce the limits for whatever if appropriate in your use case. Either with a warning dialog, or you can force the limit more strongly in code (don't offer a choice to the user).
Alternative Strategy
Alright so maybe you don't want to just get the hard margins, but rather get the soft margins and then enforce that the soft margins remain inside the printable area when printing. Let's develop another strategy here.
In this example I will use the origins at margins, and allow the user to select any margin they want, but I'm going to enforce in code that the selected margin not be outside the printable area. If the selected margins are outside the printable area, I'm simply going to adjust them to be inside the printable area.
PrintAction printAction = PrintAction.PrintToFile;
private void printDocument_BeginPrint(object sender, PrintEventArgs e)
{
// Save our print action so we know if we are printing
// a preview or a real document.
printAction = e.PrintAction;
// We ALWAYS want true here, as we will implement the
// margin limitations later in code.
printDocument.OriginAtMargins = true;
// Set some preferences, our method should print a box with any
// combination of these properties being true/false.
printDocument.DefaultPageSettings.Landscape = false;
printDocument.DefaultPageSettings.Margins.Top = 100;
printDocument.DefaultPageSettings.Margins.Left = 0;
printDocument.DefaultPageSettings.Margins.Right = 50;
printDocument.DefaultPageSettings.Margins.Bottom = 0;
}
private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics g = e.Graphics;
// If you set printDocumet.OriginAtMargins to 'false' this event
// will print the largest rectangle your printer is physically
// capable of. This is often 1/8" - 1/4" from each page edge.
// ----------
// If you set printDocument.OriginAtMargins to 'false' this event
// will print the largest rectangle permitted by the currently
// configured page margins. By default the page margins are
// usually 1" from each page edge but can be configured by the end
// user or overridden in your code.
// (ex: printDocument.DefaultPageSettings.Margins)
// Grab a copy of our "hard margins" (printer's capabilities)
// This varies between printer models. Software printers like
// CutePDF will have no "physical limitations" and so will return
// the full page size 850,1100 for a letter page size.
RectangleF printableArea = e.PageSettings.PrintableArea;
RectangleF realPrintableArea = new RectangleF(
(e.PageSettings.Landscape ? printableArea.Y : printableArea.X),
(e.PageSettings.Landscape ? printableArea.X : printableArea.Y),
(e.PageSettings.Landscape ? printableArea.Height : printableArea.Width),
(e.PageSettings.Landscape ? printableArea.Width : printableArea.Height)
);
// If we are printing to a print preview control, the origin won't have
// been automatically adjusted for the printer's physical limitations.
// So let's adjust the origin for preview to reflect the printer's
// hard margins.
// ----------
// Otherwise if we really are printing, just use the soft margins.
g.TranslateTransform(
((printAction == PrintAction.PrintToPreview)
? realPrintableArea.X : 0) - e.MarginBounds.X,
((printAction == PrintAction.PrintToPreview)
? realPrintableArea.Y : 0) - e.MarginBounds.Y
);
// Draw the printable area rectangle in PURPLE
Rectangle printedPrintableArea = Rectangle.Truncate(realPrintableArea);
printedPrintableArea.Width--;
printedPrintableArea.Height--;
g.DrawRectangle(Pens.Purple, printedPrintableArea);
// Grab a copy of our "soft margins" (configured printer settings)
// Defaults to 1 inch margins, but could be configured otherwise by
// the end user. You can also specify some default page margins in
// your printDocument.DefaultPageSetting properties.
RectangleF marginBounds = e.MarginBounds;
// This intersects the desired margins with the printable area rectangle.
// If the margins go outside the printable area on any edge, it will be
// brought in to the appropriate printable area.
marginBounds.Intersect(realPrintableArea);
// Draw the margin rectangle in RED
Rectangle printedMarginArea = Rectangle.Truncate(marginBounds);
printedMarginArea.Width--;
printedMarginArea.Height--;
g.DrawRectangle(Pens.Red, printedMarginArea);
}
Currently the following is working on my printer. I have OriginAtMargins set to false. This causes automatic translation to the HardMarginX and HardMarginY when I'm printing to my printer, but NO translation when I'm printing to the PrintPreviewControl. Therefore, I have to check for this case.
private void printDocument_BeginPrint(object sender, PrintEventArgs e)
{
printAction = e.PrintAction;
printDocument.OriginAtMargins = false;
}
private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics g = e.Graphics;
if (printAction != PrintAction.PrintToPreview)
g.TranslateTransform(-e.PageSettings.HardMarginX, -e.PageSettings.HardMarginY);
RectangleF printArea = GetBestPrintableArea(e);
g.DrawRectangle(Pens.Red, printArea.X, printArea.Y, printArea.Width - 1, printArea.Height - 1);
}
public RectangleF GetBestPrintableArea(PrintPageEventArgs e)
{
RectangleF marginBounds = e.MarginBounds;
RectangleF printableArea = e.PageSettings.PrintableArea;
RectangleF pageBounds = e.PageBounds;
if (e.PageSettings.Landscape)
printableArea = new RectangleF(printableArea.Y, printableArea.X, printableArea.Height, printableArea.Width);
RectangleF bestArea = RectangleF.FromLTRB(
(float)Math.Max(marginBounds.Left, printableArea.Left),
(float)Math.Max(marginBounds.Top, printableArea.Top),
(float)Math.Min(marginBounds.Right, printableArea.Right),
(float)Math.Min(marginBounds.Bottom, printableArea.Bottom)
);
float bestMarginX = (float)Math.Max(bestArea.Left, pageBounds.Right - bestArea.Right);
float bestMarginY = (float)Math.Max(bestArea.Top, pageBounds.Bottom - bestArea.Bottom);
bestArea = RectangleF.FromLTRB(
bestMarginX,
bestMarginY,
pageBounds.Right - bestMarginX,
pageBounds.Bottom - bestMarginY
);
return bestArea;
}
If anyone can try this code on their printer to verify that it works universally, or correct it if I'm wrong, that would be great.
I don't know if pre-translation of the origin to the hard margins when OriginAtMargins is false is standard with all printers, or if it's just doing this on my printer.
I think what you need is simply redraw the image to fit whatever the paper size being used. Here's my code:
Protected Overrides Sub OnPrintPage(ByVal e As System.Drawing.Printing.PrintPageEventArgs)
Dim img As Image = Nothing 'Your image source
Dim ps As PaperSize = MyBase.PrinterSettings.DefaultPageSettings.PaperSize
Dim pF As RectangleF = MyBase.PrinterSettings.DefaultPageSettings.PrintableArea
Dim srcF As New RectangleF(0, 0, pg.ImageSize.Width, pg.ImageSize.Height)
Dim dstF As New RectangleF(0, 0, pF.Width, pF.Height)
e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
e.Graphics.DrawImage(img, dstF, srcF, GraphicsUnit.Pixel)
MyBase.OnPrintPage(e)
End Sub

Snake in C# - player can scale window - dividing manual-scaled window into identical squares

As part of my self-education of programming I decided to make a snake in C#. The problem I have is about the client size of the game form.
I want player to be able to scale the window of the game, which is divided into 25 x 25 grid (every coordinate is like "one pixel") - it means, that at any moment, the window is divided into 25 x 25 identical squares.
The problem I get is near this code:
int SquareSide = (ClientSize.Width / 25);
When I set the ClientSize strictly to for example 600 x 600, which is a multiple of 25, everything goes OK. But when I don't (for example by manual resizing, which can change the size to, for example, 711 x 711), it creates at the right side a 'strip', which seems to be the rest of pixels, which can't be used because we are dividing to integer number.
My question is - is there any not-extremely-hard way to achieve dividing ANY client size of form into 25 x 25 grid without this problem? I tried using double, but FillRectangle method doesn't accept it.
I hope my question is understandable and thank you for replies.
To tell you the truth, there is
g.FillRectangle(Brush b, RectangleF rect)
RectangleF is a rectangle whose coordinates are float.
So you can use:
float SquareSide = (ClientSize.Width * 1f / 25);
I would try to simply handle OnResize event of the window, and at the moment user finishes rezise it, force the size that program need for perfect fit of the grid.
So for example at the moment user releases mouse and you figure out that one dimensions of the window 711x711, bring it to nearest correct fit 700x700.
In this way you guarantee good user experience on different monitor resolutions and for you guarantee a correct fit of the grid you draw.
Hope this helps.
Switch to float coordinates for everything. Make sure your game looks OK when lines do not have whole pixel coordinates. Make sure you "find next cell" code also works with floats, including mouse position detection if needed.
The other approach is to be happy with integer coordinates (and cells of the same size) and make page layout flexible to accomodate some unused space for odd 711x711 layouts (i.e. just center the field and keep some variable width border).

LinearGradientBrush Artifact Workaround?

The LinearGradientBrush in .net (or even in GDI+ as a whole?) seems to have a severe bug: Sometimes, it introduces artifacts. (See here or here - essentially, the first line of a linear gradient is drawn in the endcolor, i.e. a gradient from White to Black will start with a Black line and then with the proper White to Black gradient)
I wonder if anyone found a working workaround for this? This is a really annoying bug :-(
Here is a picture of the Artifacts, note that there are 2 LinearGradientBrushes:
alt text http://img142.imageshack.us/img142/7711/gradientartifactmm6.jpg
I have noticed this as well when using gradient brushes. The only effective workaround I have is to always create the gradient brush rectangle 1 pixel bigger on all edges than the area that is going to be painted with it. That protects you against the issue on all four edges. The downside is that the colors used at the edges are a fraction off those you specify, but this is better than the drawing artifact problem!
You can use the nice Inflate(int i) method on a rectangle to get the bigger version.
I would finesse Phil's answer above (this is really a comment but I don't have that privilege). The behaviour I see is contrary to the documentation, which says:
The starting line is perpendicular to the orientation line and passes through one of the corners of the rectangle. All points on the starting line are the starting color. Then ending line is perpendicular to the orientation line and passes through one of the corners of the rectangle. All points on the ending line are the ending color.
Namely you get a single pixel wrap-around in some cases. As far as I can tell (by experimentation) I only get the problem when the width or height of the rectangle is odd. So to work around the bug I find it is adequate to increase the LinearGradientBrush rectangle by 1 pixel if and only if the dimension (before expansion) is an odd number. In other words, always round the brush rectangle up the the next even number of pixels in both width and height.
So to fill a rectangle r I use something like:
Rectangle gradientRect = r;
if (r.Width % 2 == 1)
{
gradientRect.Width += 1;
}
if (r.Height % 2 == 1)
{
gradientRect.Height += 1;
}
var lgb = new LinearGradientBrush(gradientRect, startCol, endCol, angle);
graphics.FillRectangle(lgb, r);
Insane but true.
At least with WPF you could try to use GradientStops to get 100% correct colors right at the edges, even when overpainting.
I experienced artifacts too in my C++ code. What solved the problem is setting a non-default SmoothingMode for the Graphics object. Please note that all non-default smoothing modes use coordinate system, which is bound to the center of a pixel. Thus, you have to correctly convert your rectangle from GDI to GDI+ coordinates:
Gdiplus::RectF brushRect;
graphics.SetSmoothingMode( Gdiplus::SmoothingModeHighQuality );
brushRect.X = rect.left - (Gdiplus::REAL)0.5;
brushRect.Y = rect.top - (Gdiplus::REAL)0.5;
brushRect.Width = (Gdiplus::REAL)( rect.right - rect.left );
brushRect.Height = (Gdiplus::REAL)( rect.bottom - rect.top );
It seems like LinearGradientBrush works correctly only in high-quality modes.

Categories