Window form cannot display from second control - winforms

I am trying to add a custom control at runtime. So i created a custom control with its own paint method. Whenever the "Add" button clicked, a new control is created and added to main form. But While adding controls,I cannot see others, but first control only. I have no idea about what is happening, Can anyone help?. Thanks in advance.
public ref class CustomLine : public UserControl
{
private:
Point P1,P2;
Pen ^pen;
public:
CustomLine(Point p1, Point p2)
{
P1 = p1;
P2 = p2;
pen = gcnew Pen(Color::Red,2);
}
protected:
virtual void OnPaint(System::Windows::Forms::PaintEventArgs ^e) override
{
e->Graphics->DrawLine(pen,P1,P2);
}
};
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
int xx1 = Convert::ToInt32(this->x1->Text);
int yy1 = Convert::ToInt32(this->y1->Text);
int xx2 = Convert::ToInt32(this->x2->Text);
int yy2 = Convert::ToInt32(this->y2->Text);
CustomLine ^cline = gcnew CustomLine(Point(xx1,yy1),Point(xx2,yy2));
this->Controls->Add(cline);
this->Invalidate();
}

lc's comment resolved the issue. Thanks lc.
In the custom class,it was missed to initialize control's attributes "Location" and "Size". After initializing these attributes, the controls starts appearing in the form as expected.
public ref class CustomLine : public UserControl
{
private:
Point P1,P2;
Pen ^pen;
public:
CustomLine(Point p1, Point p2)
{
P1 = p1;
P2 = p2;
this->Location = P1;
this->Size = System::Drawing::Size(Point(P2.X - P1.X, P2.Y - P1.Y));
pen = gcnew Pen(Color::Red,2);
}
protected:
virtual void OnPaint(System::Windows::Forms::PaintEventArgs ^e) override
{
e->Graphics->DrawLine(pen,P1,P2);
}
};

Related

How to disable remove button for KryptonPage with context menu close item?

How to block KryptonPage for close and i need to remove button of docking area and context menu option for close
i am using https://github.com/ComponentFactory/Krypton
Visual Studio 2015 Community
Win 10
There are details about my code for clear understanding
Following screenshot is Form designer about using controls
screenshot of Form designer using controls 1
screenshot of Form designer using controls 2
Following screenshot of ruining application
application ruining time for close menu item for block i want it
There are my form code c#
// this is main form code
public partial class frmMain : KryptonForm
{
public frmMain()
{
InitializeComponent();
kryptonPanel1.Dock = DockStyle.Fill;
kryptonDockableWorkspace.Dock = DockStyle.Fill;
kryptonPanel.Dock = DockStyle.Fill;
}
private void Form1_Load(object sender, EventArgs e)
{
KryptonDockingWorkspace w = kryptonDockingManager.ManageWorkspace(kryptonDockableWorkspace);
kryptonDockingManager.ManageControl(kryptonPanel, w);
kryptonDockingManager.ManageFloating(this);
kryptonDockingManager.AddDockspace("Control", DockingEdge.Left, new KryptonPage[] { NewWinTools() });
kryptonDockingManager.AddDockspace("Control", DockingEdge.Bottom, new KryptonPage[] { NewWinTools(), NewWinTools(), NewWinTools(), NewWinTools() , NewWinTools() });
kryptonDockingManager.AddToWorkspace("Workspace", new KryptonPage[] { NewWinControl() });
}
private KryptonPage NewPage(string name, int image, Control content)
{
// Create new page with title and image
KryptonPage p = new KryptonPage();
p.Text = name;
p.TextTitle = name;
p.TextDescription = name;
p.ImageSmall = imageListSmall.Images[image];
// Add the control for display inside the page
content.Dock = DockStyle.Fill;
p.Controls.Add(content);
return p;
}
private KryptonPage NewWinControl()
{
UserControl1 br = new UserControl1();
KryptonPage page = NewPage("New Tab", 0, br);
page.ClearFlags(KryptonPageFlags.DockingAllowAutoHidden | KryptonPageFlags.DockingAllowDocked);
return page;
}
private KryptonPage NewWinTools()
{
UserControl1 br = new UserControl1();
KryptonPage page = NewPage("Tools 1 ", 2, br);
page.ClearFlags( KryptonPageFlags.DockingAllowClose);
return page;
}
}
please help for block close KryptonPage
I have just come across the same issue. I can see that this question was answered here
It looks like there is no way of actually removing the close button but you can intercept it and then ignore the event.
In the interest of completeness, this is the code you need to write:
private void CreateDockWorkspace()
{
KryptonDockingWorkspace w = kryptonDockingManager.ManageWorkspace("Workspace", kryptonDockableWorkspace);
kryptonDockingManager.ManageControl("Control", kryptonPanel, w);
kryptonDockingManager.ManageFloating("Floating", this);
kryptonDockingManager.AddToWorkspace("Workspace", new KryptonPage[] {
NewPage("Overview"),
NewPage("Main"),
NewPage("Report"),
});
// This is where you wire up the CloseAction event handler
var workspace = kryptonDockingManager.CellsWorkspace.FirstOrDefault();
workspace.CloseAction += HandleTabCloseAction;
}
private void HandleTabCloseAction(object sender, CloseActionEventArgs e)
{
// This event handler ignores the action
e.Action = CloseButtonAction.None;
}
private KryptonPage NewPage(string name)
{
var p = new KryptonPage();
p.Text = name;
p.TextTitle = name;
p.TextDescription = name;
content.Dock = DockStyle.Fill;
p.Controls.Add(content);
return p;
}

How can I find UIElements in a rectangle in WPF?

I need to find UIElements in (rectangle/area/bounds).
MainWindow I'm doing the following:
I register the mouse down as the start position.
I regsiter the mouse up position.
Now I need to find ll (buttons, textboxes, etc) in the rectangle between start
postion and the end position.
I found in the msdn the HitTest approach but it is only for one point. I think, walking through all points in the founded
rectangle it is a performance disaster.
http://msdn.microsoft.com/en-us/library/ms752097.aspx
My code based on MVVM pattern:
private ObservableCollection<UIElementViewModel> wells;
private Point stratPoint; // Mouse down
public ICommand MouseUpRightCommand
{
get
{
if (this.mouseUpRightCommand == null)
{
this.mouseUpRightCommand = new RelayCommands(
param =>
{
if (param is MouseButtonEventArgs)
{
var e = (param as MouseButtonEventArgs);
//Set the end point
endPosition = e.GetPosition(((ItemsControl)e.Source));
// for example, here I want to find all controls(UIElements) in the
// founded rectangle of stratPoint and endPosition.
}
});
}
return this.mouseUpRightCommand;
}
}
Any other idea or a better approach?
Thanks
I would use FrameworkElement (which extends UIElement) instead of UIElement, in order to use ActualWidth and ActualHeight properties
Then create a static class which does some math MouseUtils
with those static fields
private static double _dContainerTop;
private static double _dContainerBottom;
private static double _dContainerLeft;
private static double _dContainerRight;
private static double _dCursorTop;
private static double _dCursorLeft;
private static double _dCursorRight;
private static double _dCursorBottom;
and those static methods
private static void FindValues(FrameworkElement element, Visual rootVisual)
{
var containerTopLeft = container.TransformToAncestor(rootVisual).Transform(new Point(0, 0));
_dContainerTop = containerTopLeft.Y;
_dContainerBottom = _dContainerTop + container.ActualHeight;
_dContainerLeft = containerTopLeft.X;
_dContainerRight = _dContainerLeft + container.ActualWidth;
}
and
public static bool IsElementUnderRectCursor(FrameworkElement element, Point startPoint, Point endPoint, Visual rootVisual)
{
_dCursorTop=Math.Min(startPoint.Y, endPoint.Y);
_dCursorBottom=Math.Max(startPoint.Y, endPoint.Y);
_dCursorLeft=Math.Min(startPoint.X, endPoint.X);
_dCursorRight=Math.Max(startPoint.X, endPoint.X);
FindValues(container, rootVisual);
if (_dContainerTop < _dCursorTop|| _dCursorBottom< _dContainerBottom )
{
return false;
}
if (_dContainerLeft < _dCursorLeft|| _dContainerRight < _dCursorRight)
{
return false;
}
return true;
}
Rootvisual being your window for example;
Then loop over ObservableCollection<FrameworkElement> wells and call that function IsElementUnderRectCursor.
This is inspired from:
Kinecting the Dots
Astreal thanks again for your answer. It's done. I just moved the selection code from modelView to view. The selection done only in the UI.
private void SelectWells(RectangleGeometry selectionRectangle, FrameworkElement frameworkElement)
{
var items = GetItemsControl(frameworkElement);
foreach (var item in items.Items)
{
var viusalItem = (ContentPresenter)items.ItemContainerGenerator.ContainerFromItem(item);
var wellControl = this.GetWellControl(viusalItem);
var relativePoint = wellControl.TransformToAncestor(items).Transform(new Point(0, 0));
var controlRectangle =
new RectangleGeometry(
new Rect(relativePoint.X, relativePoint.Y, wellControl.ActualWidth, wellControl.ActualHeight));
var intersectionGeometry = Geometry.Combine(
selectionRectangle, controlRectangle, GeometryCombineMode.Intersect, null);
if (intersectionGeometry.GetArea() > 0)
{
wellControl.Command.Execute(this);
}
}
}
usefull link for u:
http://www.codeproject.com/Articles/354853/WPF-Organization-Chart-Hierarchy-MVVM-Application
When an user clicks on a node in the tree we need to let the ViewModel node know that the selection has changed. We like to route the event as a command to the ViewModel

How to set an event handler of a lower class radiobutton in an upper class?

I create a user control group sub-class. There are two radiobuttons. I need to create event handlers for them. I have two directions to go. One is to create event handlers in the sub class and let the event handler to change a constant in the subclass. I will use a function to check the sub class constant in the upper class. The other one is to create event handlers in the upper class for the sub-class radio buttons. The following is my code for method 1.Note I have commented out two lines (they are the event handler creation) because they are wrong because they create errors please help
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::Collections;
using namespace System::Collections::Generic;
#include <stdio.h>
#include <stdlib.h>
#using <mscorlib.dll>
public ref class temp_groupbox: public GroupBox
{
public: temp_groupbox(int a, int b, String ^groupboxname){
// Create and initialize a GroupBox and two RadioButton controls.
//GroupBox^ groupBox1 = gcnew GroupBox;
RadioButton^ radioButton1 = gcnew RadioButton;
RadioButton^ radioButton2 = gcnew RadioButton;
// Add the RadioButtons to the GroupBox.
this->Controls->Add( radioButton1 );
this->Controls->Add( radioButton2 );
this->Location = System::Drawing::Point(a, b);
this->Size = System::Drawing::Size(500, 100);
this->TabIndex = 0;
this->TabStop = false;
radioButton1->Name = L"radioButton1";
radioButton2->Name = L"radioButton2";
radioButton1->Size = System::Drawing::Size(85, 17);
radioButton2->Size = System::Drawing::Size(85, 17);
radioButton1->Location = System::Drawing::Point(30, 40);
radioButton2->Location = System::Drawing::Point(30, 90);
radioButton1->TabIndex = 0;
radioButton1->TabStop = true;
radioButton2->TabIndex = 1;
radioButton2->TabStop = true;
radioButton1->UseVisualStyleBackColor = true;
radioButton1->CheckedChanged += gcnew System::EventHandler(this, radioButton1_CheckedChanged);
radioButton2->UseVisualStyleBackColor = true;
radioButton2->CheckedChanged += gcnew System::EventHandler(this, radioButton2_CheckedChanged);
this->SuspendLayout();
this->ResumeLayout(false);
this->PerformLayout();
}
public: RadioButton^ radioButton1;
public: RadioButton^ radioButton2;
public: int anss;
void radioButton1_CheckedChanged(Object^ sender, EventArgs^ e)
{
anss = 1;
}
void radioButton2_CheckedChanged(Object^ sender, EventArgs^ e)
{
anss = 2;
}
};// end ref class
Do you have methods radioButton1_CheckedChanged and radioButton2_CheckedChanged defined?
void radioButton1_CheckedChanged(Object^ sender, EventArgs^ e)
{
}
void radioButton2_CheckedChanged(Object^ sender, EventArgs^ e)
{
}
If these methods already exist, please list the error message you're getting. It's hard to figure out how to fix something if we don't know what's wrong.
You need to specify the full class name of the method you're creating a delegate for, and use the & to take the address of it.
gcnew System::EventHandler(this, &temp_groupbox::radioButton1_CheckedChanged)

Proper way to call AnimateWindow with a .NET WinForms Form?

i'm trying to call AnimateWindow to animate the show and hide of a WinForms window.
Here's a copy of the win32 translation:
private static class NativeMethods
{
public const int AW_ACTIVATE = 0x20000;
public const int AW_HIDE = 0x10000;
public const int AW_BLEND = 0x80000;
public const int AW_CENTER = 0x00000010;
public const int AW_SLIDE = 0X40000;
public const int AW_HOR_POSITIVE = 0x1;
public const int AW_HOR_NEGATIVE = 0X2;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int AnimateWindow(IntPtr hwand, int dwTime, int dwFlags);
}
But the problem is how to fit a call to AnimateWindow into the) WinForms scheme. One person suggests OnLoad:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
AnimateWindow(this.Handle, 200, AW_ACTIVATE | AW_HOR_NEGATIVE | AW_SLIDE);
}
and OnClosing:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (e.Cancel == false)
{
AnimateWindow(this.Handle, 200, AW_HIDE | AW_HOR_POSITIVE | AW_SLIDE);
}
}
Except that it doesn't work.
the form doesn't use any animation while appearing
during hide the form animates its horizontal slide off the screen, then reappears, before hiding the normal way
What is the correct way to mix AnimateWindow with WinForms?
See also
.NET AnimateWindow: this guy asked the same question. But since it was trying to achieve something else, people solved his problem rather than answering his question.
C# WinForms AnimateWindow issue: This guy was interested in using AnimateWindow with child controls, rather than a top-level window.
Bonus Chatter
i was perusing through the Form -> Show -> Visible -> SetVisibleCore, when i discovered this bug:
protected virtual void SetVisibleCore(bool value)
{
try
{
HandleCollector.SuspendCollect();
//...snip...
}
finally
{
HandleCollector.ResumeCollect();
}
}
Nice to know that everyone can introduce these subtle errors.
I think AnimateWindow has it's limitations to work properly. For example, it doesn't play well with Aero, so to animate a sliding form, you would need to set the BorderStyle to None. Also, make sure the StartPosition is set to Manual.
Simple example:
public partial class Form1 : Form {
public const int AW_ACTIVATE = 0x20000;
public const int AW_HIDE = 0x10000;
public const int AW_BLEND = 0x80000;
public const int AW_CENTER = 0x00000010;
public const int AW_SLIDE = 0X40000;
public const int AW_HOR_POSITIVE = 0x1;
public const int AW_HOR_NEGATIVE = 0X2;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int AnimateWindow(IntPtr hwand, int dwTime, int dwFlags);
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
Form toastForm = new Form();
toastForm.ShowInTaskbar = false;
toastForm.StartPosition = FormStartPosition.Manual;
toastForm.FormBorderStyle = FormBorderStyle.None;
toastForm.Size = new Size(256, 64);
toastForm.Location = new Point(Screen.PrimaryScreen.WorkingArea.Right - toastForm.Width,
Screen.PrimaryScreen.WorkingArea.Bottom - toastForm.Height);
Button closeButton = new Button();
closeButton.Text = "Close";
toastForm.Controls.Add(closeButton);
closeButton.Click += delegate { toastForm.Close(); };
AnimateWindow(toastForm.Handle, 200, AW_ACTIVATE | AW_HOR_NEGATIVE | AW_SLIDE);
toastForm.Show();
}
}
I'm not sure what your AnimateWindow call does, but when you need to change underlying native 'stuff' to do with windows forms, I've always used the CreateParams() override. You may
find a similar function for what you are trying to achieve.
Here's an example of a transparent tool window, that doesn't activate when it is shown.
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim baseParams As Windows.Forms.CreateParams = MyBase.CreateParams
baseParams.ExStyle = baseParams.ExStyle Or NativeMethods.ExtendedWindowsStyles.WS_EX_LAYERED Or NativeMethods.ExtendedWindowsStyles.WS_EX_TRANSPARENT Or NativeMethods.ExtendedWindowsStyles.WS_EX_NOACTIVATE Or NativeMethods.ExtendedWindowsStyles.WS_EX_TOOLWINDOW
Return baseParams
End Get
End Property

Why is only the first shown window focusable

Imagine the code below. Only the first window appears on the top, all of subsequent windows won't nor can they be programatically focused for some reason (they appear in the background). Any idea how to workaround this? BTW, static methods/properties are not allowed nor is any global property.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread t1 = new Thread(CreateForm);
t1.SetApartmentState(ApartmentState.STA);
t1.Start();
t1.Join();
t1 = new Thread(CreateForm);
t1.SetApartmentState(ApartmentState.STA);
t1.Start();
t1.Join();
}
private static void CreateForm()
{
using (Form f = new Form())
{
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer
{
Enabled = true,
Interval = 2000
};
t.Tick += (s, e) => { f.Close(); t.Enabled = false; };
f.TopMost = true;
Application.Run(f);
}
}
Hans Passant solved the problem: just use SetForegroundWindow() (P/Invoke). Shees, I should have though of that :-)

Resources