Why is only the first shown window focusable - winforms

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 :-)

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 do I prevent multiple instances of Process.start?

I have a button on my WinForm. Code works great until I observed my test users.
They don't wait for the PDF to launch. Instead they will click it several times (causing multiple instances of the Acrobat reader to launch
private void pictureBoxNewsLetter_Click(object sender, EventArgs e)
{
lockControls();
launchNewsLetter();
unlockControls();
}
private void launchNewsLetter()
{
// Newsletter
lockControls();
ProcessStartInfo psi = new ProcessStartInfo(#"Y:\Newsletter.pdf");
Process ps = new Process { StartInfo = psi };
ps.Start();
ps.WaitForExit();
Thread.Sleep(1000);
unlockControls();
}
--- Code to disable my controls.
private void lockControls()
{
dontRunHandler = false;
foreach (var pb in this.Controls.OfType<PictureBox>())
{
pb.Enabled = false;
}
}
private void unlockControls()
{
dontRunHandler = true;
foreach (var pb in this.Controls.OfType<PictureBox>())
{
pb.Enabled = true;
}
}

datagridview control continues update, gui flickers when scrolling window

Problem:
I have a Winform application with a form en on this form i have a databound DataGridView.
The datagridview is updated from the backend by updating the bind object continuesly using a timer to get the data every 10 seconds. In order to update the gui with this new data i call a RefreshDatabindings. (if i do not do this, the gui is nog updated, i am binding to a BindingList and the object implement the INotifyPropertyChanged)
When the form is big enough to show the whole datagridview at once everything is working wel. But when the form is not big enough to show the hole datagridview a scrollbar appears.
When i scroll to the right to see the rest of the datagridview i see the gui flickering (only the part that wasn't visible before scrolling). When i strech the form to make de gridview fitting again, everything is working wel (no flashing and flickering). the flickering only happens when i have to scroll.
I am lost, can please somebody help me :)?
I allready tryed the DoubleBuffered = true.
Thanks in advance!
BindingList<InstanceTableViewModel> viewModelList;
public Form1()
{
InitializeComponent();
DoubleBuffered = true;
functionParamList = new List<FunctionParameter>();
functionParamList.Add(new FunctionParameter { DeviceValue = 100, InstanceId = "1", Name = "A" });
functionParamList.Add(new FunctionParameter { DeviceValue = 200, InstanceId = "2", Name = "B" });
functionParamList.Add(new FunctionParameter { DeviceValue = 300, InstanceId = "3", Name = "C" });
viewModelList = CreateInstanceTableViewModelList();
dataGridView1.DataSource = viewModelList;
//Create timer
updateDataTimer = new System.Timers.Timer();
updateDataTimer.Interval = 500;
updateDataTimer.Elapsed += updateDataTimer_Elapsed;
updateDataTimer.Start();
}
private void updateDataTimer_Elapsed(object sender, ElapsedEventArgs e)
{
ThreadPool.QueueUserWorkItem(ReadDataThreadPoolMethod);
}
private void ReadDataThreadPoolMethod(object state)
{
Random random = new Random();
int randomNumber = random.Next(0, 100);
foreach (FunctionParameter param in functionParamList)
{
param.DeviceValue = Convert.ToInt64(randomNumber);
}
}
void functionParameter_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
var functionParameter = sender as FunctionParameter;
var propertyName = e.PropertyName;
var propertyValue = functionParameter.DeviceValue;
var parameterName = functionParameter.Name;
UpdateViewModel(functionParameter.InstanceId, propertyName, propertyValue, parameterName);
}
private void UpdateViewModel(string instanceId, string propertyName, long propertyValue, string parameterName)
{
var instanceViewModel = viewModelList.Single(x => x.InstanceId == instanceId && x.NameLabel == parameterName);
if (instanceViewModel != null)
{
instanceViewModel.ValueHex = Convert.ToUInt16(propertyValue);
}
ResetBindingsSource();
}
delegate void UpdateBindingsInvoker();
public void ResetBindingsSource()
{
if (!this.IsDisposed)
{
if (this.InvokeRequired)
{
this.Invoke(new UpdateBindingsInvoker(UpdateDataGrid));
}
else
{
UpdateDataGrid();
}
}
}
private void UpdateDataGrid()
{
dataGridView1.Refresh();
}
So here my solution:
You only uses the Forms DoubleBuffering, but the following code is an extension method to the DataGridview and successfully works (at my tests ;)
public static void DoubleBuffered(this DataGridView dgv, bool setting)
{
Type dgvType = dgv.GetType();
PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(dgv, setting, null);
}
I found this code right here at Codeprojct.
You can use it in this way:
YourDataGridView.DoubleBuffered(true);
I hope i could help you ^^

wpf threading, thread must be STA

I have a window(say main window) with a frame which has a page in it. A button on the page opens another window(say popup window). Now i am trying to invoke a method in the main window from a button on the popup window. The method has to be multi-threaded, i had a similar solution running in windows forms but i keep getting the calling thread must be STA because many UI components require this in WPF.
The method on the page which opens the popup window modally
Scripts showStocks = new Scripts();
showStocks.ShowInTaskbar = false;
showStocks.ShowDialog();
if (showStocks.DialogResult==true)
{
Window1 wd1 = new Window1();
wd1.doneDeal();
}
Here window1 is our main window. The doneDeal method is
public void doneDeal()
{
// **Some Code**
BackgroundWorker wworks1 = new BackgroundWorker();
wworks1.DoWork += Tickes;
wworks1.RunWorkerCompleted += Tickes2;
wworks1.RunWorkerAsync();
// Page1 pg1 = frame1.Content as Page1;
//NextPrimeDelegate dd=new NextPrimeDelegate(okreport);
// pg1.addScriptBtn.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
// new NextPrimeDelegate(okreport));
//startStopButton.Dispatcher.BeginInvoke(
// DispatcherPriority.Normal,
// new NextPrimeDelegate(CheckNextNumber));
//new Thread(() => Tick(stock, rowID, exchange)) { IsBackground = false }.Start();
}
Finally the method that i am trying to run in the background
public void Tickes(object sender, DoWorkEventArgs e)
{
}
Also i want to populate a gridview from the result of the tickes method, this will be looping and running over and over in the background but periodically returning data to be added to the grid. SHould i do that in the progress update event ? Have tried a lot to wrap my head around the dispatcher and background worker in wpf but am failing to understand the STA apartment state bit. If someone can help me to get my tickes method going or point me in the right direction, i would be very very thankful.
Well i finally was able to solve the STA thread problem am posting the answer just in case somebody comes across a similar problem in the future.
public void doneDeal()
{
if (StockData.flag == 1)
{
row1 = table.NewRow();
row1[col1] = "";
row1[col2] = "";
row1[col3] = "";
row1[col4] = "";
row1[col5] = "";
row1[col6] = "";
row1[col7] = "";
row1[col8] = "";
row1[col9] = "";
row1[col10] = "";
row1[col11] = "";
row1[col12] = "";
table.Rows.Add(row1);
string stock = StockData.stock;
int rowID = (table.Rows.Count - 1);
string exchange = StockData.exchange;
Thread bh = new Thread(delegate()
{
Tick7(stock, rowID, exchange);
});
bh.SetApartmentState(ApartmentState.STA);
bh.IsBackground = true;
bh.Start();
StockData.flag = -1;
}
}
The Tick7 method which is being called is declared like this
[STAThread]
public void Tick7(string stock, int rowID, string exchange)
{
int rowNum = rowID;
int counter = -1;
deletecounter = StockData.deletecounter;
Thread.CurrentThread.Name = StockData.stock;
.
.
.
}

WPF closing child- closes parent-window

i have the pretty same sample as mentioned here.
Fast concluded: MainWindow closes when the last childwindow is closed.
My Problem: I couldn't solve my problems with the described solutions. I can't produce a program where it als takes place. Only in one of my bigger progs. Maybe someone has an idea or knows any further steps.
Thanks for reading - Thomas
As requested here's a bit of code:
This is the part in the MainWindow:
bool editAfterSearch = false;
Movie selectedMovie = (Movie)this.listView.SelectedItem;
Movie backup = (Movie)selectedMovie.Clone();
if (new OnlineSearchWindow().EditMovieViaOnlineSearch(ref selectedMovie, out editAfterSearch))
{
this.coverFlow.Update(selectedMovie);
}
And that's the part of the ChildWindow:
public bool EditMovieViaOnlineSearch(ref Movie preset, out bool editAfter)
{
this.exitWithOk = false;
this.editMovieAfterSearch = false;
this.tbx_SearchTerm.Text = preset.Title;
this.linkedMovie = preset;
this.ShowDialog();
editAfter = editMovieAfterSearch;
if (this.exitWithOk)
{
this.linkedMovie.CloneOnlineInformation(ref preset);
preset.Bitmap = this.linkedMovie.Bitmap;
return true;
}
else
{
return false;
}
}
Try playing with the ShutDownMode property of your App.xaml.cs. The 3 values are OnMainWindowClose, OnLastWindowClose, and OnExplicitShutdown, and the default is OnLastWindowClose
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
this.ShutdownMode = System.Windows.ShutdownMode.OnMainWindowClose;
}
}
The below code worked for me.
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (MessageBoxResult.No == (MessageBox.Show("Are you sure you want to close this?.", "ProjectName", MessageBoxButton.YesNo)))
{
e.Cancel = true;
foreach (var item in Application.Current.Windows)
{
Window window = item as Window;
if (window.Title == "PopUpWindowName")
{
window.Topmost = true;
break;
}
}
return;
}
else
{
base.OnClosed(e);
Application.Current.Shutdown();
}
}
you can try setting the child window's allowShutDown to false and then show the mainwindow. I'm assuming you will start with mainwindow's visibility set to hidden.
Application.Current.MainWindow.Visibility = System.Windows.Visibility.Visible;
this.allowShutDown = false;
The allowShutDown will be your own property which u can set to enable you have to handle the closing event.

Resources