Draw boder outside button which is placed inside panel at run time - winforms

I am developing a window application. I have a static panel on form & Some menu like panel buttons etc.
at run time I have drag a panel on static panel & add a button inside this panel. now a I want to drawn a border outside this button but when border is drawn , border take its position from static panel not from panel createdat run time.
Please provide me a sol. for this .
My code for draw border is :
private void sDrawControlBorder(object sender)
{
Control control = (Control)sender;
//define the border to be drawn, it will be offset by DRAG_HANDLE_SIZE / 2
//around the control, so when the drag handles are drawn they will be seem
//connected in the middle.
Rectangle Border = new Rectangle(
new Point(control.Location.X - DRAG_HANDLE_SIZE / 2,
control.Location.Y - DRAG_HANDLE_SIZE / 2),
new Size(control.Size.Width + DRAG_HANDLE_SIZE,
control.Size.Height + DRAG_HANDLE_SIZE));
//define the 8 drag handles, that has the size of DRAG_HANDLE_SIZE
Rectangle NW = new Rectangle(
new Point(control.Location.X - DRAG_HANDLE_SIZE,
control.Location.Y - DRAG_HANDLE_SIZE),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle N = new Rectangle(
new Point(control.Location.X + control.Width / 2 - DRAG_HANDLE_SIZE / 2,
control.Location.Y - DRAG_HANDLE_SIZE),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle NE = new Rectangle(
new Point(control.Location.X + control.Width,
control.Location.Y - DRAG_HANDLE_SIZE),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle W = new Rectangle(
new Point(control.Location.X - DRAG_HANDLE_SIZE,
control.Location.Y + control.Height / 2 - DRAG_HANDLE_SIZE / 2),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle E = new Rectangle(
new Point(control.Location.X + control.Width,
control.Location.Y + control.Height / 2 - DRAG_HANDLE_SIZE / 2),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle SW = new Rectangle(
new Point(control.Location.X - DRAG_HANDLE_SIZE,
control.Location.Y + control.Height),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle S = new Rectangle(
new Point(control.Location.X + control.Width / 2 - DRAG_HANDLE_SIZE / 2,
control.Location.Y + control.Height),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
Rectangle SE = new Rectangle(
new Point(control.Location.X + control.Width,
control.Location.Y + control.Height),
new Size(DRAG_HANDLE_SIZE, DRAG_HANDLE_SIZE));
//get the form graphic//
g = control.Parent.CreateGraphics();
//draw the border and drag handles//
ControlPaint.DrawBorder(g, Border, Color.Gray, ButtonBorderStyle.Dotted);
ControlPaint.DrawGrabHandle(g, NW,true,true);
ControlPaint.DrawGrabHandle(g, N, true, true);
ControlPaint.DrawGrabHandle(g, NE, true, true);
ControlPaint.DrawGrabHandle(g, W, true, true);
ControlPaint.DrawGrabHandle(g, E, true, true);
ControlPaint.DrawGrabHandle(g, SW, true, true);
ControlPaint.DrawGrabHandle(g, S, true, true);
ControlPaint.DrawGrabHandle(g, SE, true, true);
g.Dispose();
}

Related

Set image position to page center

I'm trying to print an image in the center of the page but I can't come up with any idea.
System.Windows.Point printLocation = new System.Windows.Point(50,50);
printLocation.X = pageWidth - 50 / 2; 50 is the margin
imageViewer = ImagePrintAdapter.CreateImageFromBitmapImage(img,printLocation);
printerDialog.PrintVisual(imageViewer, "Identification");
This is the CreateImageFromBitmapImagemethod
public static System.Windows.Controls.Image CreateImageFromBitmapImage(BitmapImage imgSource, System.Windows.Point imgLocation)
{
System.Windows.Controls.Image imageViewer = new System.Windows.Controls.Image();
imageViewer.BeginInit();
imageViewer.Source = imgSource;
imageViewer.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
imageViewer.Arrange(new System.Windows.Rect(imgLocation, imageViewer.DesiredSize));
imageViewer.EndInit();
imageViewer.UpdateLayout();
return imageViewer;
}
If I set the printLocation.X to be the half of the pageWidth, shouldn't it start at the center ?
You may simply draw the image into a DrawingVisual and print it. The following simplified example assumes that the bitmap size is smaller than the printable area size:
ImageSource image = ...
var rect = new Rect(
(printDialog.PrintableAreaWidth - image.Width) / 2,
(printDialog.PrintableAreaHeight - image.Height) / 2,
image.Width, image.Height);
var visual = new DrawingVisual();
using (var dc = visual.RenderOpen())
{
dc.DrawImage(bitmap, rect);
}
printDialog.PrintVisual(visual, "");
Note that you may as well use any other size for the Rectangle, i.e. scale the printed image accordingly.

WPF Grid + Splitter + FlowDocumentScrollViewer

I have a WPF Grid with 4 rows:
Row 0 : Height = 1.0 (Grid Unit Type Star)
Row 1 - GridSplitter. Height GridLength.Auto
Row 2 - Height Fixed (About 20px)
Row 3 - FlowDocumentScrollViewer: Height GridLength.Auto
Row 1. 2, 3 are initially hidden (for this reasong height of row1 = 1.0). When clicking a button row 1, 2 and 3 are made visible.
I can't drag the splitter to make the flow document scroll viewer smaller.
If I drag the splitter to make it bigger, the Row 2 grows but the row 3 keeps with the same height.
¿How can I get the row 3 growing or shrunking properly? I post my code below:
void BuildComponents()
{
mainGrid= new Grid();
RowDefinition row0 = new RowDefinition();
RowDefinition splitterRow = new RowDefinition();
RowDefinicion fixedHeightRow = new RowDefinition();
RowDefinition scrolldocumentRow= new RowDefinition();
row0.Height = new GridLength(1.0, GridUnitType.Star);
splitterRow.Height = GridLength.Auto;
fixedHeightRow .Height = new GridLength(20, GridUnitType.Pixel);
scrolldocumentRow.Height = GridLength.Auto;
mainGrid.RowDefinitions.Add(row0);
mainGrid.RowDefinitions.Add(splitterRow);
mainGrid.RowDefinitions.Add(fixedHeightRow );
mainGrid.RowDefinitions.Add(scrolldocumentRow);
mainGrid.Children.Add(/*Grid Panel */);
mainGrid.Children.Add(Splitter);
mainGrid.Children.Add(/* Panel */);
mainGrid.Children.Add(/* Flow Document Scroll Viewer */);
Thank you

WPF multipage printing for FixedDocument (Visual C# 2010)

I have a question about multipage FixedPage. I have a Grid created programmatically and the Grid exceeds one A4 page. Now I want to print the Grid in several FixedPage with print margin. But on my way, I create the Grid repeatedly and offset the LeftTop point in the fixedPage Arrange function. I meet a problem that I cannot set print margin in fixedPage, because I set the print margin to the fixedPage and then the first page will have print margin and the next pages will be blank.
How do print multipage of FixedDocument for a large grid want to print?
PrintDialog pd = new System.Windows.Controls.PrintDialog();
if (pd.ShowDialog() == false)
{
return;
}
var pageSize = new Size(pd.PrintableAreaWidth, pd.PrintableAreaHeight);
var document = new FixedDocument();
document.DocumentPaginator.PageSize = pageSize;
for (int nPage = 0; nPage < MaxPage; nPage++)
{
Grid tempGrid = LoadControlMotherInit();
tempGrid.Width = GridWidth;
tempGrid.Height = GridActualHeight;
Point leftTop = new Point();
leftTop.X = 10;
leftTop.Y = -nPage * pageSize.Height;
// Create FixedPage
var fixedPage = new FixedPage();
fixedPage.Width = pageSize.Width;
fixedPage.Height = pageSize.Height;
fixedPage.Margin = new Thickness(0, 0, 0, 96);
fixedPage.Children.Add((UIElement)tempGrid);
fixedPage.Measure(pageSize);
fixedPage.Arrange(new Rect(leftTop, pageSize));
fixedPage.UpdateLayout();
// Add page to document
var pageContent = new PageContent();
((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
document.Pages.Add(pageContent);
}
pd.PrintDocument(document.DocumentPaginator, "My Document");
From looking at your example,
PrintDialog.PrintDocument method takes in a DocumentPaginator, which could come from a multitude of source.
that being said, you can inherit from DocumentPaginator and take control of everything from PageSize, PageCount to the actual DocumentPage being returned.
Imagine your DocumentPage as a sliding window over your UIElement; but instead of sliding your DocumentPage, you slide your UIElement using its RenderTransform.

Wrong coordinates on multiple monitors

I have a Datagrid and I want to know the position of a datacell for overlaying it with a window.
It works fine with only one monitor, but with multiple monitors, the window is displaced.
Here's the code:
Point point = cell.PointToScreen(new Point(0, 0));
...
Window myWindow = new Window();
myWindow.Top = point.Y;
myWindow.Left = point.X;
Somebody has some experience with positioning on multiple monitors?
EDIT:
I made following test:
public MyWindow()
{
...
this.LocationChanged += MyWindow_LocationChanged;
}
void MyWindow_LocationChanged(object sender, EventArgs e)
{
Console.WriteLine(this.Top + " <--> " + this.PointToScreen(new Point(0, 0)).Y);
}
Results:
- Single-Monitor: 0 <--> 30; 20 <--> 50; 100 <--> 130
==> Always difference of 30 (may be caused by title bar)
- Dual-Monitor: 0 <--> 30; 20 <--> 55; 100 <--> 153
==> At 0,0 difference of 30. But the more I moved the window away from 0,0. the greater becomes the difference, but should stay the same. Very strange!
EDIT2:
Here's my solution, thanks to CodeNaked for the hint:
Point point = cell.PointToScreen(new Point(0, 0));
...
Window myWindow = new Window();
PresentationSource source = PresentationSource.FromVisual(this);
myWindow.Top = point.Y / source.CompositionTarget.TransformToDevice.M22;
myWindow.Left = point.X / source.CompositionTarget.TransformToDevice.M11;
This may have to do with a non-standard DPI setting, but I'm pretty sure that setting affects all monitors. This blog shows how to get the correct position. But the code is effectively:
PresentationSource source = PresentationSource.FromVisual(control);
double dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11;
double dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22;
window.Left = point.X * 96.0 / dpiX;
window.Top = point.Y * 96.0 / dpiY;
The behavior you described is not correct and I can't reproduce it.
I created a simple Window with the following code:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LocationChanged += (s, e) =>
{
var screen = PointToScreen(new Point(0, 0));
var window = new Point(Left, Top);
var diff = screen - window;
textbox.Text = window.ToString() + Environment.NewLine +
screen.ToString() + Environment.NewLine + diff;
};
}
}
The last line (= the difference between the two coordinates) never changes.
I'm unable to reproduce the problem your experience. The upper left corner of the client area of the window (the point returned by PointToScreen) is always translated 8 pixels horizontally and 30 pixels vertically from the upper left corner of the window. This is on a two-monitor setup.
You should be able to compute the values 8 and 30 from the SystemParameters class, however I must admit that I'm not sure exactly what parameters to use to arrive at the actual values on my system.

WPF/Path - geometry consisting of multiple lines with different line width?

I have the need for drawing in the same drawing with lines of different color, thickness etc.
I can create two instances of PathGeometry, but I can't set color on them.
I can create two instances of Path, but can't get them displayed in my control.
What am I doing wrong?
Thanks for any comments!
Anders, Denmark.
Code below only displays "collection" in my control, but I thought it could be a starting point for answers...
var pathFigure1 = new PathFigure(new Point(0, 0),
new List<PathSegment> {new LineSegment(new Point(10, 10), true)}, false);
var pathFigure2 = new PathFigure(new Point(20, 20),
new List<PathSegment> {new LineSegment(new Point(30, 30), true)}, false);
var g1 = new PathGeometry(new List<PathFigure> {pathFigure1});
var g2 = new PathGeometry(new List<PathFigure> {pathFigure2});
var p1 = new System.Windows.Shapes.Path
{
Data = g1,
Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 0))
};
var p2 = new System.Windows.Shapes.Path
{
Data = g2,
Stroke = new SolidColorBrush(Color.FromRgb(170, 87, 170))
};
var content = new Canvas();
content.Children.Add(p1);
content.Children.Add(p2);
Content = content;
You have started on the right approach, a geometry defines a 'shape', so don;t worry that you cannot set its colour. A Path turns the geometry into a visual representation on the screen, so here you can set the color and stroke thickness.
Your problem is at the very last step, you are setting the content property of your control. Typically this property is used to associate some data object with a control, you then supply a template which is its visual representation.
What you need to do is add your paths as children of a panel.
For example, add a Canvas, or a Grid to your control. Then add your two paths to the Grid / Canvas via their Children collection property.

Resources