I would like to achieve the same effect like in this article but for windows forms, is it even possible without hosting the control on different Form?
EDIT
I'm more interested in implementing the exact behavior of the control in the article, showing the control on the form and blocking the calling function, but without using other form for this purpose.
You can create a UserControl with the two buttons and the label for the message, then set its visibility to false in the constructor:
public MyDialog()
{
InitializeComponent();
Visible = false;
}
Then you add three variables to the control:
Form _parent;
bool _result;
bool _clicked = false;
the parent Form will be the Form your control is contained in and must be set before using the control, since it has to know what has to be disabled.
public void SetParent(Form f)
{
_parent = f;
}
_result will contain the result of the dialog, and _clicked will be used to determine when to close your dialog. What has to be done when you show your dialog is:
set the label
disable the form (but not the dialog)
make the dialog visible
wait for the user to click one of the buttons
hide the dialog
reenable the parent form
return the result
So you could add this method to enable/disable the parent form:
private void ParentEnabled(bool aBool)
{
if (_parent == null)
return;
foreach (Control c in _parent.Controls)
if (c != this)
c.Enabled = aBool;
}
and use it in the ShowDialog method:
public bool ShowDialog(string msg)
{
if (_parent == null)
return false;
// set the label
msgLbl.Text = msg;
// disable the form
ParentEnabled(false);
// make the dialog visible
Visible = true;
// wait for the user to click a button
_clicked = false;
while (!_clicked)
{
Thread.Sleep(20);
Application.DoEvents();
}
// reenable the form
ParentEnabled(true);
// hide the dialog
Visible = false;
// return the result
return _result;
}
Obviously the buttons have the responsibility to set the _result and _clicked variables:
private void okBtn_Click(object sender, EventArgs e)
{
_result = true;
_clicked = true;
}
private void cancelBtn_Click(object sender, EventArgs e)
{
_result = false;
_clicked = true;
}
How about creating transparent form that in the middle contains text on opaque shape (whatever you like). Then at runtime you would resize this form to have same size as the window over which you want to display it and place it so that it covers it.
Related
I don't want to click on a button or the form, I just want to know if user is pressing the left mouse button while the cursor is in the form.
I've tried this:
private void PlayForm_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.LButton)
{
...
}
}
but it doesn't work.
I also tried PlayForm_Click() but it works only when the click is on the 'canvas' if there's something else on top it won't work
If you just want to know if the left mouse button is down while executing some other code in the Form you can look at the static property Control.MouseButtons, which returns a value from the MouseButtons enumeration .E.g.:
if ((Control.MouseButtons & MouseButtons.Left) != 0)
you could use the mouse enter/leave to set a boolean that the mouse cursor is over the form, then you could Use the Mouse.
...
bool mouseOverMe;
public MainWindow()
{
InitializeComponent();
mouseOverMe = false;
}
private void Window_MouseEnter(object sender, MouseEventArgs e)
{
mouseOverMe = true;
}
private void Window_MouseLeave(object sender, MouseEventArgs e)
{
mouseOverMe = false;
}
void doSomething()
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
if (mouseOverMe)
MessageBox.Show("Im a mouse down in the window");
}
...
something sorta like this.
As far as I've understood, you want a handler for a click on whatever is in the form. I'd suggest you could iterate trough all the controls in the form on Form_Load event and just set a common handler for the MouseClick (or KeyPressed or whichever event you want according to your current need) for all controls present in the .Controls collection in the moment the form is loaded and you should register the same handler for the form itself (a.k.a. this.MouseClick). This will be a bit of an overkill if you'd later want to register a MouseClick handler for a particular control, but you can always compare the sender object and get the data from there. Example code is not present for now, since I'm typing from my phone. Will update later.
The main problem is that the form doesn't get any messages when a message is sent directly to a child control.
One way around this is to register an application-wide message filter. Note that the following implementation is rather inefficient (and quite ugly), but it should show you the basic idea:
void Main()
{
var form = new Form();
form.Load += (s, _) => Application.AddMessageFilter(new MyFilter((Form)s));
var pnl = new Panel();
pnl.Controls.Add(new Button());
form.Controls.Add(pnl);
Application.Run(form);
}
public class MyFilter : IMessageFilter
{
Form form;
public MyFilter(Form form)
{
this.form = form;
this.form.Disposed += (_, __) => Application.RemoveMessageFilter(this);
}
public bool PreFilterMessage(ref Message msg)
{
const int WM_LMOUSEDOWN = 0x0201;
if (msg.Msg == WM_LMOUSEDOWN && msg.HWnd != IntPtr.Zero
&& Control.FromHandle(msg.HWnd).TopLevelControl == form)
{
Console.WriteLine("Hi!");
}
return false;
}
}
i'm working on a project for school and have some logical errors.
I have 2 different forms: frmOrders and frmCustomers. frmOrders is the main form and when i click a button here, frmCustomers will show. There is a datagrid named txtTable in frmCustomers.
Now, what i want to do is when I double click a row, some of the info goes in some textboxes in frmOrders then frmCustomers closes. Also, i want the rest of the controls in frmCustomers to be disabled. (I have set the access modifiers for the controls in frmCustomers as public but it does't seem to work.) How do I do that?
Currently this is my code:
public partial class frmOrders : Office2007Form
{
public frmOrders()
{
InitializeComponent();
}
private void frmOrders_Load(object sender, EventArgs e)
{
}
private void btnCustomer_Click(object sender, EventArgs e)
{
frmCustomers c = new frmCustomers();
c.ShowDialog();
c.txtAddress.Enabled = false;
c.txtBday.Enabled = false;
c.txtContactNo.Enabled = false;
c.txtFname.Enabled = false;
c.txtLname.Enabled = false;
c.txtMI.Enabled = false;
c.txtSearch.Enabled = false;
c.btnDelete.Enabled = false;
c.btnSave.Enabled = false;
c.btnUpdate.Enabled = false;
}
}
I guess your buttons, textfields, etc. are private fields in your frmCustomers form code (frmCustomers.Designer.cs), so they cannot be accessed from another form. Either you make your controls public (which I do not suggest) or you add a public method to your form (frmCustomers) that sets the properties and can be accessed from frmOrders.
For example (in your frmCustomers code):
public void SetControlsEnabled()
{
txtAddress.Enabled = false;
txtBday.Enabled = false;
txtContactNo.Enabled = false;
...
}
But as long as you invoke your form with ShowDialog() the code below does not execute because it waits for the form to close (and it returns a DialogResult).
So do it this way
frmCustomers c = new frmCustomers();
c.SetControlsEnabled();
c.ShowDialog();
Hope this helps!
here i have this problem with popup window, i popup an usercontrol in a dll and call this dll in an app, but it shows upon a black page that i have no idear where its from. when i push the '<-' button ,the app directly exit... i can't go back to the app's mainpage where calls it.
I wonder how can I return from the popup window. I tried to hide the popup window, but it doesn't go back to app's mainpage.
public void change_PIN(OnCCB_ChangeUserPINCall changeUserPINCall)
{
Popup ppChangePIN = new Popup();
ChangePIN changePIN = new ChangePIN();
ppChangePIN.Child = changePIN;
ppChangePIN.IsOpen = true;
}
How can I set ppChangePIN.IsOpen=false inside popup window .cs to make it disappear?
Handle back key press event of back button like
step1: first set one flag when popup is open like **bool PopupOpen=True**
step2: When popup is close at that time PopupOpen=False
protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
if(PopupOpen== True)
{
ppChangePIN.IsOpen=false;
PopupOpen=False;
e.Cancel = true;
}
else
{}
}
If any query let me know...
hope it work for you
private bool RemovePopup()
{
if (ppChangePIN == null || !ppChangePIN.IsOpen)
return false;
ppChangePIN.IsOpen = false;
return true;
}
protected override void OnBackKeyPress(CancelEventArgs e)
{
if (RemovePopup())
e.Cancel = true;
}
I was wondering how I would make an image appear inside a messagebox that I set up so that whenever the mouse enters a label, it displays the messagebox. What would the code be for the image insertion?
Quick and dirty way to achieve this is to create another windows form that will have same buttons as message box but that will also have an image.
Create public Boolean property in this form that will be named something like OKButtonClicked that will tell you whether OK or Cancel was clicked
Set ControlBox property to False so that minimize, maximize and close buttons are not shown
Here is a code behind for this form
public partial class MazeForm : Form
{
public MazeForm()
{
InitializeComponent();
}
private bool okButton = false;
public bool OKButtonClicked
{
get { return okButton; }
}
private void btnOK_Click(object sender, EventArgs e)
{
okButton = true;
this.Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
okButton = false;
this.Close();
}
}
Finally in your main form you can do something like this
MazeForm m = new MazeForm();
m.ShowDialog();
bool okButtonClicked = m.OKButtonClicked;
Note that this is something I quickly created in 15 min and that it probably needs more work but it will get you in the right direction.
I have a form. In that I got to show a dialog (on some circumstances) with Text and a Cancel button. I want to catch the event of that button in my form Or know if that cancel button was clicked.
How can this be done ? I believe this should be possible but can't make out how ?
From my mainForm I have BackgroundWorker. When the backgroundWorker is started I open a childForm (with a Label and a button) and when the background task is over, I close the childForm. What I want more is : when the button of childForm is clicked the ongoing task of backgroundWorker should be cancelled.
SOLUTION
In my childForm I have set CancelButton property as cancelBtn for the form. The othe code is :
private bool cancel;
public bool Cancel
{
get { return cancel; }
set { cancel = value; }
}
// Set the flag as true to indicate that Cancel button was actually pressed
private void cancelBtn_Click(object sender, EventArgs e)
{
Cancel = true;
}
In mainForm :
childDlg = new ChildDialog();
// wHILE cALLING
backgroundWorker1.RunWorkerAsync();
msg = "Connecting...";
childDlg .set(msg, "");
if (!childDlg .IsAccessible)
{
// This is caught even when the dialog is closed
if (childDlg .ShowDialog() == DialogResult.Cancel) {
if (childDlg.Cancel == true) { // Was really cancelBtn pressed
// NOW ONLY do my stuff
}
}
}
I had tried using #DeveloperX technique i.e. EventHandler in parent class, but the parent class method was nver being called. Tried a lot but couldn't success. Then tried of #RobinJ's technique and it worked. I just had to add flag to identify was really cancel button pressed or jjst windw was closed normally.
Thanks to all of you for tryig to help me out. I really appreciate your help.
Thanks
Set DialogResult property to either DialogResult.Ok or DialogResult.Cancel
Then in the parent form:
Form form = new Form();
DialogResult results = form.DialogResult;
if(results == DialogResult.Ok)
{
... make magic
}
else
{
...
}
Put this in the form that should catch the event:
frmDialog.ShowDialog();
And this in the btnCancel_Click event of the dialog:
return DialogResult.Cancel();
Sorry if I'm confusing VB and C# here, but it's pretty much the same.
Simply you can create an event for the form that shows the dialog
and handle this event in parent form
in case the user clicks on ok fire event with specefic parameter and for cancel another parameter (such dialogresult.cancel)
an pseudo implementation can be like this
public class FormChild : System.Windows.Forms.Form
{
public event EventHandler DialogCanceled;
public event EventHandler DialogConfirmed;
public void ShowDialog()
{
using (var dialogForm = new FormDialog())
{
if (dialogForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
if (DialogConfirmed != null)
DialogConfirmed(this,new EventArgs());
}
else
{
if (DialogCanceled != null)
DialogCanceled(this,new EventArgs());
}
}
}
}
public class ParentForm : System.Windows.Forms.Form
{
public void callChild()
{
using (var f = new FormChild())
{
f.DialogCanceled += new EventHandler(f_DialogCanceled);
f.DialogConfirmed += new EventHandler(f_DialogConfirmed);
f.ShowDialog();
}
}
void f_DialogConfirmed(object sender, EventArgs e)
{
throw new NotImplementedException();
}
void f_DialogCanceled(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
You should be using the ShowDialog method on the form you need to show as a dialog and then use the DialogResult property to communicate to the parent form the result of the dialog operation.
This way you handle the button click on the form that owns the button but set the DialogResult to DialogResult.Cancel to specify that the user pressed the cancel button.
A dialog is usually a blocking event, where eventhandling by the parent form would make no sense at all.
If it isn't a modal dialog, you can always create one or several public events in the popup form, that are triggered when the buttons are clicked. These events can then be caught by the parent form.
Don't expose your buttons to the parent form, it would be terrible oo-programming.
Use the following:
Form form = new Form();
switch (form.ShowDialog())
{
case DialogResult.Ok:
{
....
Break;
}
case DialogResult.Cancel:
{
....
Break;
}
}
Set the Form.AcceptButton and Form.CancelButton properties to the appropriate buttons.
Refer to the following:
Form.ShowDialog Method
DialogResult Enumeration
Form.AcceptButton Property
Form.CancelButton Property