Scenario
I'm in need of help using a KryptonSeparator.
I would like to use the separator in the image below to resize the width of the left and right controls:
Problem
The problem is when I try to move the separator to the left then it creates a very disturbing visual effect, and more or less the same thing happens when I move the separator to the right, but to the left is much more appreciable (and horrible):
I think that I'm not using properly the eventargs of the KryptonSeparator because when I move the separator to the left I'm basing the calculations using the separator's width instead the event data (because I don't know how to do it properly).
Question
What modifications I should do in my code to fix the resizing problem?
Code
Both the left and the right control has a MinimumSize property assigned, I'm trying to stop the resize if MinimumSize.Width is reached.
This is the source code, in VB.Net:
''' <summary>
''' Handles the SplitterMoving event of the KryptonSeparator1 control.
''' </summary>
Private Sub KryptonSeparator1_SplitterMoving(ByVal sender As Object, ByVal e As SplitterCancelEventArgs) _
Handles KryptonSeparator1.SplitterMoving
Dim separator As KryptonSeparator = DirectCast(sender, KryptonSeparator)
Dim leftCtrl As Control = Control1
Dim rightCtrl As Control = Control2
If (e.MouseCursorX > 0) _
AndAlso Not ((rightCtrl.Size.Width - e.MouseCursorX) < rightCtrl.MinimumSize.Width) Then
separator.Location = New Point(separator.Location.X + e.MouseCursorX, separator.Location.Y)
leftCtrl.Width += e.MouseCursorX
rightCtrl.Width -= e.MouseCursorX
rightCtrl.Left = separator.Right
ElseIf (e.MouseCursorX < 0) _
AndAlso Not ((leftCtrl.Size.Width + e.MouseCursorX - separator.Width) < leftCtrl.MinimumSize.Width) Then
separator.Location = New Point(separator.Location.X - separator.Width, separator.Location.Y)
leftCtrl.Width -= separator.Width
rightCtrl.Width += separator.Width
rightCtrl.Left = separator.Right
End If
End Sub
This is the source code, in C#:
/// Handles the SplitterMoving event of the KryptonSeparator1 control.
/// </summary>
private void KryptonSeparator1_SplitterMoving(object sender, SplitterCancelEventArgs e)
{
KryptonSeparator separator = (KryptonSeparator)sender;
FolderView leftCtrl = this.FolderView_Files;
KryptonListBox rightCtrl = this.KryptonListBox_Files;
if ((e.MouseCursorX > 0) && !((rightCtrl.Size.Width - e.MouseCursorX) < rightCtrl.MinimumSize.Width)) {
separator.Location = new Point(separator.Location.X + e.MouseCursorX, separator.Location.Y);
leftCtrl.Width += e.MouseCursorX;
rightCtrl.Width -= e.MouseCursorX;
rightCtrl.Left = separator.Right;
} else if ((e.MouseCursorX < 0) && !((leftCtrl.Size.Width + e.MouseCursorX - separator.Width) < leftCtrl.MinimumSize.Width)) {
separator.Location = new Point(separator.Location.X - separator.Width, separator.Location.Y);
leftCtrl.Width -= separator.Width;
rightCtrl.Width += separator.Width;
rightCtrl.Left = separator.Right;
}
}
//=======================================================
//Service provided by Telerik (www.telerik.com)
//=======================================================
UPDATE
I've updated the codes above to simplify the reading, and I'm sharing this new video where you can see the design problem:
www.youtube.com/watch?v=-MhmyE3MZX0
First, you need to get where the user clicked before the dragging,mouse down event of splitter control and total width of three controls:
Private mouse_Down As Point //you can use an integer also because y coordinate remains the same
Private totalWidth As Integer
//mouse down event
mouse_Down.X = e.MouseCursorX
totalWidth = seperator.Width + LeftControl.Width + RightControl.Width
Private Sub KryptonSeparator1_SplitterMoving(ByVal sender As Object, ByVal e As SplitterCancelEventArgs) Handles KryptonSeparator1.SplitterMoving
Dim separator As KryptonSeparator = DirectCast(sender, KryptonSeparator)
Dim leftCtrl As Control = Control1
Dim rightCtrl As Control = Control2
Dim leftWidth, rightWidth As Integer
leftWidth = leftCtrl.Width + (e.MouseCursorX - mouse_Down.X)
rightWidth = rightCtrl.Width - (e.MouseCursorX - mouse_Down.X)
If leftWidth <= leftCtrl.MinimumSize.Width Then
leftCtrl.Width = leftCtrl.MinimumSize.Width
separator.Left = leftCtrl.Left + leftCtrl.MinimumSize.Width
rightCtrl.Left = leftCtrl.Left + leftCtrl.MinimumSize.Width + separator.Width
rightCtrl.Width = totalWidth - leftCtrl.MinimumSize.Width - separator.Width
Return
End If
If rightWidth <= rightCtrl.MinimumSize.Width Then
leftCtrl.Width = totalWidth - rightCtrl.MinimumSize.Width - separator.Width
separator.Left = leftCtrl.Left + leftCtrl.Width
rightCtrl.Left = leftCtrl.Left + leftCtrl.Width + separator.Width
rightCtrl.Width = rightCtrl.MinimumSize.Width
Return
End If
separator.Left += (e.MouseCursorX - mouse_Down.X)
leftCtrl.Width = leftWidth
rightCtrl.Width = rightWidth
rightCtrl.Left = leftCtrl.Left + leftWidth + separator.Width
End Sub
EDIT
Try this:
//mouse down event
//mouse_Down.X = e.MouseCursorX
mouse_Down.X = MousePosition.X
mouse_Down.Y = MousePosition.Y
mouse_Down = seperator.PointToClient(mouse_Down)
totalWidth = seperator.Width + LeftControl.Width + RightControl.Width
and in SplitterMoving:
Dim leftWidth, rightWidth As Integer
Dim pnt As Point
pnt.X = MousePosition.X
pnt.Y = MousePosition.Y
pnt = seperator.PointToClient(pnt)
//replace e.MouseCursorX with pnt.X
...
EDIT 2
Your logic of resizing the two windows have two minor bugs:
Using e.MouseCursorX to determine the direction of the resizing(left or right) is wrong, eg you move the cursor to the left(left direction),
remaining inside the separator, e.MouseCursorX is still positive, so you are resizing to the right(until of course e.MouseCursorX becomes negative)
instead of left !
Your code checks for the minimum size but does nothing when the comparison is false, meaning when the resulting size of the control is smaller.
When that happens you need to actually set the size of the control eg lets say the minimum size is 50 and the controls size is 55. If the resize is very fast, the resulting size of the control may become 49. Your code does nothing(comparison is false) and the size of
the control remains 55 instead of seting it to 50.
My solution solves both of these situations. However, the real issue of your horible effect as you said is not these two bugs. It is actually,
the way too slow responsiveness of the application, when you resize the controls. To be more specific, when you resize and move the right
control(ListBox_Files). You can check it your self if you drag and drop a small number(1 or 2) of files and see the result. It is a tremendous
difference. That unfortunately tells me that you can not do anything about it. You need to change the logic of the resize. Two solutions:
Use one control and custom draw everything, text, icons, vertical-horizontal scrollbars etc.. (not recommended!)
Do what visual studio and other application is doing. Do not resize the controls until you release the button. Just show a vertical line:
Related
I'm using WinForms. In My form i have a button and a panel. When i click on that button i want to slide the panel to the right. I'm having issues with the code. Currently I'm getting red error lines under
= panel2.Location.X + 1;
Error Message: Cannot implicitly convert type int to System.Drawing.Point
I was trying to move the panel with the similar approach i did by growing the panel. I provided that in my code. How can i move the panel?
private void btn_Right_Click(object sender, EventArgs e)
{
// Make Panel Grow
//while (panel1.Width < 690)
//{
// panel1.Width = panel1.Width + 1;
//}
while (panel2.Location.X < 690)
{
panel2.Location = panel2.Location.X + 1;
}
}
You get an error because you try to set the location with an integer. You will need a new point instance:
panel2.Location = new Point(panel2.Location.X, panel2.Location.Y + 1);
Try using .Left instead of .Location.X
This works in VB...
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
If sender.text = ">" Then
Do Until Panel1.Left > Me.Width - 50
Panel1.Left += 1
Loop
sender.text = "<"
Else
Panel1.Left = 511
sender.text = ">"
End If
End Sub
I'm surprised it is a smooth as it is - panel is empty however.
I am trying to add content in the detail section of ActiveReport. But the section height is limited to 2 inches. It is taking only (2/0.2 = )10 items. I want the section to increase its height as the contents increase, so that it can adopt all item. It seems like .CanGrow is not working. The code I am using is as below.
Dim lObjSecRpt As New GrapeCity.ActiveReports.SectionReport()
Dim lObjLbl As New GrapeCity.ActiveReports.SectionReportModel.Label()
Dim c As Single = 0.2F
Try
lObjSecRpt.Sections.InsertPageHF()
lObjSecRpt.Sections(0).BackColor = Color.WhiteSmoke
lObjSecRpt.Sections(0).Height = 0.0F
lObjSecRpt.Sections.Insert(1, New GrapeCity.ActiveReports.SectionReportModel.Detail())
lObjSecRpt.Sections(1).BackColor = Color.WhiteSmoke
lObjSecRpt.Sections(1).CanGrow = True
For Each dr As DataRow In mObjDtReport.Rows
lObjLbl = New GrapeCity.ActiveReports.SectionReportModel.Label()
lObjLbl.Alignment = GrapeCity.ActiveReports.Document.Section.TextAlignment.Left
lObjLbl.Font = New System.Drawing.Font("Arial", 10, FontStyle.Regular)
lObjLbl.Location = New PointF(0.0F, c)
lObjLbl.Height = 0.2F
lObjLbl.Width = 1.0F
lObjLbl.Text = CStr(dr("RptObjNam"))
lObjSecRpt.Sections(1).Controls.Add(lObjLbl)
c += c
Next
Me.rptViewer.LoadDocument(lObjSecRpt)
Ammar,
What you are trying to do in the code is creating sections and adding controls to the sections on the fly. So this is like creating a report layout at runtime. Since you are simply adding controls to the detail section, the format event for the detail section will not fire for each control as it is not bound to any data. Rather you are just adding controls to it. You can check and example of creating reports on the fly here.
If you want that the detail section should grow to show all the added controls, then you will need to increment its height on the basis of the total height of the controls inside it. For example check the sample code below which demonstrates how this can be done. You can simply add this code to the Form_Load event to verify it.
Dim lObjLbl As New GrapeCity.ActiveReports.SectionReportModel.Label()
Dim c As Single = 0.2F
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim rpt As New GrapeCity.ActiveReports.SectionReport
rpt.Sections.InsertPageHF()
rpt.Sections(0).BackColor = Color.Yellow
rpt.Sections(0).Height = 1.0F
rpt.Sections.Insert(1, New GrapeCity.ActiveReports.SectionReportModel.Detail())
rpt.Sections(1).Name = "Detail"
rpt.Sections("Detail").BackColor = Color.Gainsboro
rpt.Sections("Detail").CanGrow = True
Dim i As Integer
For i = 0 To 20
Dim lObjLbl As New GrapeCity.ActiveReports.SectionReportModel.Label()
lObjLbl.Alignment = GrapeCity.ActiveReports.Document.Section.TextAlignment.Left
lObjLbl.Font = New System.Drawing.Font("Arial", 10, FontStyle.Regular)
lObjLbl.Location = New PointF(0.0F, c)
lObjLbl.Size = New SizeF(1.0F, 0.2F)
lObjLbl.Text = "Record: " + i.ToString()
lObjLbl.BackColor = Color.Aqua
rpt.Sections("Detail").Controls.Add(lObjLbl)
c += 0.2
Next
Dim height As Double = 0
For Each control As GrapeCity.ActiveReports.SectionReportModel.ARControl In rpt.Sections("Detail").Controls
height = height + control.Height
Next
rpt.Sections("Detail").Height = height
Viewer1.LoadDocument(rpt)
End Sub
I hope this helps.
I am currently working on a sort of image processing tool that will contain certain selection tools.
In order to show the current selection to the user (for example a circle) three events are used (all inside a certain canvas):
public MainWindow()
{
InitializeComponent();
}
private Ellipse _ellip = new Ellipse();
private Point _p = new Point();
private bool _mouse = false;
private double _xcor, _ycor;
private void mouseDown(object sender, MouseButtonEventArgs e)
{
_p = Mouse.GetPosition(canvas1);
_xcor = _p.X;
_ycor = _p.Y;
_mouse = true;
}
private void newPos(object sender, MouseEventArgs e)
{
if (mouse)
{
_ellip.Visibility = Visibility.Visible;
_p = Mouse.GetPosition(canvas1);
_ellip.Margin = new Thickness((_xcor + _p.X) / 2 - Math.Sqrt((_xcor - _p.X) * (_xcor - _p.X) + (_ycor - _p.Y) * (_ycor - _p.Y)) / 2, (_ycor + _p.Y) / 2 - Math.Sqrt((_xcor - _p.X) * (_xcor - _p.X) + (_ycor - _p.Y) * (_ycor - _p.Y)) / 2, 0, 0);
ellip.Height = Math.Sqrt((_xcor - _p.X) * (_xcor - _p.X) + (_ycor - _p.Y) * (_ycor - _p.Y));
ellip.Width = Math.Sqrt((_xcor - _p.X) * (_xcor - _p.X) + (_ycor - _p.Y) * (_ycor - _p.Y));
}
InvalidateVisual();
}
private void mouseUp(object sender, MouseButtonEventArgs e)
{
mouse = false;
ellip.Visibility = Visibility.Hidden;
}
This works all fine under one condition: There is some kind of shape behind the circle. Somehow the events MouseLeftButtonDown/Up and MouseMove are not raised if used on empty area in the canvas1. Once I e.g. create a rectangle filling out the canvas, everything works just fine. But that brings with it another problem: If the rectangle is bigger than the canvas it basically goes out of the canvas and the events also work outside of the canvas (as long it is on top of the rectangle).
I really don't understand what is going wrong here.
Mouse button actions are recognized by WPF only if hit testing indicates that there is "something" under the mouse pointer. Therefore, you should implement HitTestCore(PointHitTestParameters) on your canvas.
Here is an explanation how to override default hit testing: http://msdn.microsoft.com/en-us/library/ms752097.aspx#overriding_default_hit_testing .
I have two related problems that occur in the following situation.
I have a winforms window that contains some panels. In a few of these panels there are a number of (custom) wpf user-controls.
1
if i check .Visible on the elementhost it always returns true. even though I can see that its not visible.
2
if i check .Height it will always give me the same size. even though the control itself shows a variable number of things and changes size acordingly (through Visibility.collaps);
how can I get to the correct values?
edit: code added
Okey Now I'm officialy going crazy.
If I add a few messageboxes in my code to check when and in what order the above code gets executed. When I do this everything works! but as soon as I delete the messageboxes it reverses the effect. Instead of getting bigger when needed it gets smaller en vice versa....
wtf wpf!
private Size bereken_panel(Panel P)
{
Size Sz = new Size();
int tmp_H = 42;
foreach (Control SC in P.Controls)
{
if (SC is SplitContainer)
{
if (SC.Visible)
{
tmp_H += SC.Height;
}
}
else if (SC is System.Windows.Forms.Integration.ElementHost)
{
if ((SC as System.Windows.Forms.Integration.ElementHost).Child.Visibility == System.Windows.Visibility.Visible)
{
tmp_H += (int)(SC as System.Windows.Forms.Integration.ElementHost).Child.RenderSize.Height;
}
}
}
// tmp_H = 42 + n_showed * 25;
if (tmp_H < 65)
{
tmp_H = 65;
}
Sz.Height = tmp_H;
Sz.Width = 432;
return Sz;
}
so this is after some extra modification
to clarify where the TopLeft point is.
int p_x_links = panel1.Width / 2 - 436;
int p_x_rechts = panel1.Width / 2 + 4;
//links
p_contact_gegevens.Size = bereken_panel(p_contact_gegevens);
p_telnrs.Location = new Point(p_x_links, p_contact_gegevens.Size.Height + p_contact_gegevens.Location.Y + 8);
p_telnrs.Size = bereken_panel(p_telnrs);
p_bezoekadres.Location = new Point(p_x_links, p_telnrs.Size.Height + p_telnrs.Location.Y + 8);
p_bezoekadres.Size = bereken_panel(p_bezoekadres);
//rechts
p_administratie.Size = bereken_panel(p_administratie);
p_postadres.Location = new Point(p_x_rechts, p_administratie.Size.Height + p_administratie.Location.Y + 8);
p_postadres.Size = bereken_panel(p_postadres);
Most probabbly the control is overlapped by some other control. Visibility property in this case can be even True.
Try to use ActualWidth instead.
EDIT
Sorry, the example is on ActualWidth, but you are asking for Height. Concept is the same btw.
I have made a program that measures distances from two user placed pictureboxes. At the moment it all works fine except, where i want the dots to go the pictureboxes do not go into that location where i clicked. This is my current code in Mouseclick event of the picturebox the two dots (pictureboxes) are to be placed and measure in:
if (Dotter == 1)
{
dot1.Visible = true;
dot1.Location = e.Location;
Dotter = 2;
}
else if (Dotter == 2)
{
dot2.Visible = true;
dot2.Location = e.Location;
Dotter = 1;
}
This is the actual placing function for the two pictureboxes at the moment, please help.
Thanks
Extra Info:
It is in the picturebox where the image which can be measured using these two dots, and is in its mouseclick event, and its on a Windows Form. Also when i click they are placed but are miles away from where i clicked, and sometimes even appear outside the picturebox when they shouldn't be.
Thanks for your help this is what i have done to make it work. I have changed the e.Location part of my code to this:
if (Dotter == 1)
{
dot1.Visible = true;
dot1.Left = e.Location.X + capturebox.Left - 10;
dot1.Top = e.Location.Y + capturebox.Top - 10;
Dotter = 2;
}
else if (Dotter == 2)
{
dot2.Visible = true;
dot2.Left = e.Location.X + capturebox.Left - 10;
dot2.Top = e.Location.Y + capturebox.Top - 10;
Dotter = 1;
}
So basically changing the dot's locations to Left and Top and then getting the mouse click location for x and y and then made the point at which the dot will appear to be in the middle of it by minusing 10 from each.