I am trying to make my treeview's checkboxes bigger. According to MSDN it says by default state images are capped at 16x16 and in order to use larger state images I need to specify this entry in the app.config file:
<appSettings>
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />
</appSettings>
I tried adding this to my app.config and it did not change a thing, problem is the framework seems to actually shrink the images when I use 32x32 checkboxes.
Here is how I draw and set the checkboxes in my treeview's constructor:
public class MultiStateTreeView : TreeView
{
public MultiStateTreeView() : base()
{
ImageList ilStateImages = new ImageList();
ilStateImages.ImageSize = new Size(32, 32);
for (int i = 0; i <= 4; i++)
{
Bitmap bmpCheckBox = new Bitmap(32, 32);
Graphics gfxCheckBox = Graphics.FromImage(bmpCheckBox);
switch (i)
{
case 0: cbsState = CheckBoxState.UncheckedNormal; break;
case 1: cbsState = CheckBoxState.CheckedNormal; break;
case 2: cbsState = CheckBoxState.MixedNormal; break;
case 3: cbsState = CheckBoxState.UncheckedDisabled; break;
case 4: cbsState = CheckBoxState.UncheckedDisabled; break;
}
CheckBoxRenderer.DrawCheckBox(gfxCheckBox, new Point(2, 2), cbsState);
gfxCheckBox.Save();
ilStateImages.Images.Add(bmpCheckBox);
}
base.CheckBoxes = true;
this.StateImageList = ilStateImages;
}
}
Is there something that I am missing?
Related
I'm trying to pull text from a PDF using iText7. I'm using the IEventListener to get all the parts of the page, though some of the text is rotated. I can find examples for how to insert rotated text into a PDF, but can't find anything about how I can tell if a given text segment is rotated.
Can anyone help ?
public void EventOccurred(IEventData data, EventType type)
{
PdfPart part = null;
switch (type)
{
case EventType.BEGIN_TEXT:
break;
case EventType.RENDER_TEXT:
part = new PdfTextPart(PageNumber, data as TextRenderInfo);
Parts.Add(part);
break;
case EventType.END_TEXT:
break;
case EventType.RENDER_IMAGE:
var imageData = data as ImageRenderInfo;
//this.HandleImage(imageData);
break;
case EventType.RENDER_PATH:
part = new PdfLinePart(PageNumber, data as PathRenderInfo);
Parts.Add(part);
break;
case EventType.CLIP_PATH_CHANGED:
break;
default:
break;
}
}
public PdfTextPart(Int32 pageNumber, TextRenderInfo info) : base(pageNumber)
{
Text = info.GetText();
var font = info.GetFont().GetFontProgram().GetFontNames();
Font = font.GetFontName();
if (font.IsItalic()) { this.IsItalic = true; }
if (font.IsBold()) { this.IsBold = true; }
if (font.IsUnderline()) { this.IsUnderline = true; }
}
TextRenderInfo has a base line. This base line is a LineSegment and as such has a start point and an end point. Now you merely have to determine the angle of the line between those two points.
I.e. for a TextRenderInfo info:
LineSegment baseline = info.GetBaseline();
Vector startPoint = baseline.GetStartPoint();
Vector endPoint = baseline.GetEndPoint();
Vector direction = endLocation.Subtract(startLocation);
double angle = Math.Atan2(direction.Get(Vector.I2), direction.Get(Vector.I1));
The result obviously is in radian measure.
You may additionally have to take into account the page rotation which (if I recall correctly) is not calculated into the coordinates above.
Is there any way of setting the Z-order of controls on a panel to always be on top when a new control is added? I am creating a card game and I have a Panel with the pictures of the cards in (a new picturebox for each card). When a new picture is added it automatically goes to the back of the panel. Is there any way so it will be always on top? I've tried 'SetChildIndex' but the name of each picturebox will be the same as I'm re-using code. Any help is appreciated. Thanks
private void DealPlayerCard(int cardNum)
{
string Card = Classes.Deck.GetCurrentCard();
PictureBox pb = new PictureBox() { Width = 172, Height = 240, SizeMode = PictureBoxSizeMode.StretchImage };
pb.ImageLocation = #"Cards\" + Card + ".png";
int order = 0;
switch (cardNum)
{
case 1:
pb.Location = new Point(0, 0);
order = 5;
break;
case 2:
pb.Location = new Point(60, 0);
order = 4;
break;
case 3:
pb.Location = new Point(120, 0);
order = 3;
break;
case 4:
pb.Location = new Point(180, 0);
order = 2;
break;
case 5:
pb.Location = new Point(240, 0);
order = 1;
break;
}
AddPlayerCard(pb, order);
}
public void AddPlayerCard(PictureBox pb, int order)
{
pnlPlayer.Controls.Add(pb);
pnlPlayer.Controls.SetChildIndex(pb, order);
}
EDIT
Using Sinatr's idea, I have now used the .Tag control property to give the z-order number to each of the controls and then whenever I add a control - simply loop through each control and set the z-order = .Tag property
private void DealPlayerCard(int cardNum)
{
string Card = Classes.Deck.GetCurrentCardPicture();
PictureBox pb = new PictureBox() { Width = 172, Height = 240, SizeMode = PictureBoxSizeMode.StretchImage };
pb.ImageLocation = #"Cards\" + Card + ".png";
switch (cardNum)
{
case 1:
pb.Location = new Point(0, 0);
pb.Tag = 5;
break;
case 2:
pb.Location = new Point(60, 0);
pb.Tag = 4;
break;
case 3:
pb.Location = new Point(120, 0);
pb.Tag = 3;
break;
case 4:
pb.Location = new Point(180, 0);
pb.Tag = 2;
break;
case 5:
pb.Location = new Point(240, 0);
pb.Tag = 1;
break;
}
AddPlayerCard(pb);
AddToHand("Player");
}
public void AddPlayerCard(PictureBox pb)
{
pnlPlayer.Controls.Add(pb);
foreach (Control Control in pnlPlayer.Controls)
{
pnlPlayer.Controls.SetChildIndex(Control, Int32.Parse(Control.Tag.ToString()));
}
}
You can use the BringToFront() method, available to every Winform control:
controlName.BringToFront();
This brings the control controlName to the top of the z-order, forcing it to have a z-order of 0.
You can SetChildIndex(System.Windows.Forms.Control child, int newIndex) to set the z-order.
A control with newIndex set to 0, is at the top of the z-order. Controls with higher newIndex will be positioned closer to the bottom.
I am building a map editor to easily create 2d levels. To visualize how my level looks like I am using a canvas. On this canvas I can select which block is filled with a certain type ( like solid ). I did add click and drag but because I am live drawing on the canvas it goes very slow and if you draw at a decent speed it skips several block which needs to be drawn.
I already have tried several options ( doing it in another thread. Putting it first in a queue ) but none had a good result.
I use the following code to draw my rectangles:
if (currentMap != null)
{
mapCanvas.Children.Clear();
mapCanvas.Width = (currentMap.Breedte * blockScale);
mapCanvas.Height = (currentMap.Hoogte * blockScale);
for (int i = 0; i < currentMap.Hoogte; i++)
{
for (int j = 0; j < currentMap.Breedte; j++)
{
Rectangle blok = new Rectangle();
blok.Stroke = new SolidColorBrush(Colors.Black);
blok.StrokeThickness = 0.3;
blok.Width = blockScale;
blok.Height = blockScale;
switch (currentMap.GetElement(j, i))
{
case 0:
blok.Fill = new SolidColorBrush(Colors.LightGray);
break;
case 1:
blok.Fill = new SolidColorBrush(Colors.Red);
break;
case 2:
blok.Fill = new SolidColorBrush(Colors.Green);
break;
case 3:
blok.Fill = new SolidColorBrush(Colors.Orange);
break;
case 4:
blok.Fill = new SolidColorBrush(Colors.Yellow);
break;
default:
blok.Fill = new SolidColorBrush(Colors.Black);
break;
}
blok.SetValue(Canvas.LeftProperty, (double)(blockScale * j));
blok.SetValue(Canvas.TopProperty, (double)(blockScale * i));
mapCanvas.Children.Add(blok);
}
}
}
I did came across a solution to draw faster on a canvas on this link:
Speed up adding objects to Canvas In WPF
But the problem I cannot seem to get it working in my current project or a test project.
I hope you guys can help me to speed the drawing up or at least that it can recognize every block it needs to draw.
For further question please ask I will try to give as much detail as needed
I want to programmatically create a panel and add some pictureBoxes where i select the image through a for loop. I tried lots of ways but the form shows empty.
My code is :
private void draw_pipeline()
{
Panel pnl = new Panel();
pnl.Size = new System.Drawing.Size(1130, 145);
pnl.Location = new Point(380, 260);
pnl.BorderStyle = BorderStyle.FixedSingle;
for (int i =0; i<3; i++)
{
PictureBox pic = new PictureBox();
pic.SizeMode = PictureBoxSizeMode.Zoom;
switch (i)
{
case 0:
{
pic.Location = new Point(3, 15);
pic.Size = new Size(73, 121);
pic.Image = new Bitmap("if.png"); break;
}
case 1:
{
pic.Location = new Point(76, 15);
pic.Size = new Size(73, 121);
pic.Image = new Bitmap("line.png"); break;
}
}
pnl.Controls.Add(pic);
}
}
the result i want to create is illustrated in the picture below, that contains two picture boxes with two images, if.png which is the if-box image and the line.png which is the line image. I repeat the result of my code is that form shows empty!! Any help?
You'll need to add the Panel to the Form at some point, in the same way you're adding PictureBoxes to the Panel:
this.Controls.Add(pnl);
(The this is assuming that your draw_pipeline method belongs to the Form to which you're trying to add the Panel.)
I have a UniformGrid which containts a bunch of buttons and when the UniformGrid first displays it cycles through animating each button to appear. This all works fine but when the user pushes a certain button all the buttons are removed from the grid and some new ones are created in and again are animated.
Here is how I create the buttons in code
int ModelsAnimateIndex = 0; // Index of button to animate
private void GetModels()
{
DirectoryInfo di = new DirectoryInfo(Globals.ModelsPath);
FileInfo[] fis = di.GetFiles();
// ugModels is the UniformGrid
switch (fis.Length)
{
case 1:
ugModels.Rows = 1;
ugModels.Columns = 1;
break;
case 2:
ugModels.Rows = 1;
ugModels.Columns = 2;
break;
case 3:
case 4:
ugModels.Rows = 2;
ugModels.Columns = 2;
break;
case 5:
case 6:
ugModels.Rows = 2;
ugModels.Columns = 3;
break;
case 7:
case 8:
case 9:
ugModels.Rows = 3;
ugModels.Columns = 3;
break;
default:
break;
}
foreach (FileInfo s in fis)
{
ugModels.Children.Add(new Button()
{
Background = ThemeColour, // SolidBrush
Foreground = new SolidColorBrush(Colors.White),
Name = "btn" + s.Name.Split('.')[0].Replace(" ",""),
Style = MainButtonStyle, // Button Style
Content = s.Name.Split('.')[0]
});
}
}
and now the button click event which starts animating the newly created buttons
private void btnModelSelect_Click(object sender, System.Windows.RoutedEventArgs e)
{
// TODO: Add event handler implementation here.
sbShowMenuButton.Completed += new EventHandler(sbShowModels_Completed);
Storyboard.SetTargetName(sbShowMenuButton.Children[0], ((Button)ugModels.Children[ModelsAnimateIndex]).Name);
Storyboard.SetTargetName(sbShowMenuButton.Children[1], ((Button)ugModels.Children[ModelsAnimateIndex]).Name);
Storyboard.SetTargetName(sbShowMenuButton.Children[2], ((Button)ugModels.Children[ModelsAnimateIndex]).Name);
sbShowMenuButton.Begin((Button)ugModels.Children[ModelsAnimateIndex]); // Error is here
}
When the first button tries to animate I get the following error
'btnTestModel' name cannot be found in the name scope of 'System.Windows.Controls.Button'.
I have solved my problem. I needed to create the RenderTransform on the buttons created like so.
foreach (FileInfo s in fis)
{
ugModels.Children.Add(new Button()
{
Background = ThemeColour,
// This Fixed the problem //
RenderTransform = new TransformGroup()
{
Children = new TransformCollection()
{
new ScaleTransform(),
new SkewTransform(),
new RotateTransform(),
new TranslateTransform()
}
},
////////////////////////////////////////////////
BorderBrush = null,
Foreground = new SolidColorBrush(Colors.White),
Name = "btn" + s.Name.Split('.')[0].Replace(" ", ""),
Margin = new Thickness(12, 12, 12, 12),
FontSize = 48,
Style = MainButtonStyle,
Content = s.Name.Split('.')[0]
});
}
thanks to Matt's sugestion, I also modified setting the storyboard
private void btnMenu_Click(object sender, System.Windows.RoutedEventArgs e)
{
sbShowMenuButton.Completed += new EventHandler(sbShowModels_Completed);
Storyboard.SetTarget(sbShowMenuButton, ((Button)ugModels.Children[ModelsAnimateIndex]));
sbShowMenuButton.Begin();
}