UserControl doesn't show up - c#-4.0

I'm working on a kind of Screen manager, here's the code:
/// <summary>
/// Change the screen according to type
/// </summary>
/// <author>Kay van Bree</author>
/// <param name="type">Replacement screen type</param>
public void ChangeScreen(ScreenType type)
{
// Swap old screen with loading screen
ReplaceScreen(screen, new LoadingScreen(this));
UserControl newScreen;
// Get instance of correct screen
switch(type)
{
case ScreenType.login:
newScreen = new LoginScreen(this);
break;
case ScreenType.dashboard:
newScreen = new DashboardScreen(this);
break;
default:
newScreen = new LoginScreen(this);
break;
}
// Swap loading screen with new screen
ReplaceScreen(screen, newScreen);
Text = "Attendance Tracker | " + screen;
}
private void ReplaceScreen(UserControl oldScreen, UserControl newScreen)
{
Controls.Remove(oldScreen);
screen = newScreen;
// Initialize screen
newScreen.BackColor = Color.Transparent;
newScreen.Location = new Point((Size.Width - screen.Size.Width) / 2, (Size.Height - screen.Size.Height) / 2);
Controls.Add(newScreen);
}
The goal of this function is to show a Loading Screen while it's initializing another UserControl (the screens are subclasses of UserControl). When the UserControl is initialized it removes the Loading screen and adds the UserControl to controls.
The problem is that my Loading screen (also a UserControl) won't show up. It won't execute any code before the other UserControl has been initialized.
I can't seem to find a solution, or what the problem is at all. Can you explain this behaviour? Am I approaching the loading screen wrong? Does C# load the constructor in a different thread or something? What's the problem?
[edit] By the way. The loading screen is just something I wanted to add in. The rest of the screen manager works just fine, so if I'm approaching it wrong, I'll probably drop the whole loading thing.

A simple Refresh() solved my problem.

Related

How is the PinchSlider meant to be configured?

I tried using the slider component for the first time and immediately some question came up:
How do I make the slider snap to the positions of the TickMarks?
If that's not possible, what are they for?
How do I change the amount of marks or remove all of them if I want to slider without stepping?
Why, when I change the Slider Track settings the visuals do not adjust?
I already see this going into a feature request ;)
These questions are probably best filed as issues on the MRTK github page. here's a link to file an issue.
But, answering your questions here for future visitors:
How do I make the slider snap to the positions of the TickMarks?
The default PinchSlider does not provide that functionality, but here is an example of how to do this by extending pinchslider (reference: issue 4140
public class SliderWithSnapPoints : PinchSlider
{
[SerializeField]
[Tooltip("The number of snap points")]
float snapPoints = 100;
float lastSnapPoint;
float snapPointSize;
public override void OnPointerDown(MixedRealityPointerEventData eventData)
{
base.OnPointerDown(eventData);
if (eventData.used)
{
lastSnapPoint = SliderValue;
snapPointSize = 1f / snapPoints;
}
}
/// <summary>
/// Handle slider value changes by dragging, and commit these changes.
/// </summary>
/// <remarks>
/// Note, this requires the MRTK pinch slider to implement this function signature,
/// and the pinch slider needs to call this function instead of instead setting SliderValue
/// directly.
/// </remarks>
protected override void OnPointerDragged(float newSliderValue)
{
var valueChange = Mathf.Abs(lastSnapPoint - newSliderValue);
if (valueChange >= snapPointSize)
{
lastSnapPoint = SliderValue = newSliderValue;
}
}
}
How do I change the amount of marks or remove all of them if I want to slider without stepping?
You can just delete or disable the tick marks in the scene hierarchy.
Why, when I change the Slider Track settings the visuals do not adjust?
The visuals do not adjust because they are not tied to the number of snap points, they are just provided for visual guidance.
I modified this implementation slightly:
using Microsoft.MixedReality.Toolkit.UI;
using UnityEngine;
public class SliderWithSnapPoints : PinchSlider
{
#pragma warning disable 649
[Tooltip("The number of snap points")]
[Min(2)]
[SerializeField] private int snapPoints = 5;
#pragma warning restore 649
/// <summary>
/// Handle slider value changes by dragging, and commit snap point aligned changes.
/// </summary>
/// <remarks>
/// Note, this requires the MRTK pinch slider to implement this function signature,
/// and the pinch slider needs to call this function instead of setting SliderValue
/// directly.
/// </remarks>
protected override void OnPointerDragged(float newSliderValue)
{
float gap = 1f / (snapPoints - 1f);
newSliderValue = 0.5f * gap + newSliderValue;
newSliderValue -= (newSliderValue % gap);
SliderValue = newSliderValue;
}
}
As the comment suggests you also have to edit the main PinchSlider script from:
public void OnPointerDragged(MixedRealityPointerEventData eventData)
{
if (eventData.Pointer == activePointer && !eventData.used)
{
var delta = activePointer.Position - startPointerPosition;
var handDelta = Vector3.Dot(SliderTrackDirection.normalized, delta);
SliderValue = Mathf.Clamp(startSliderValue + handDelta / SliderTrackDirection.magnitude, 0, 1);
// Mark the pointer data as used to prevent other behaviors from handling input events
eventData.Use();
}
}
To:
public void OnPointerDragged(MixedRealityPointerEventData eventData)
{
if (eventData.Pointer == activePointer && !eventData.used)
{
var delta = activePointer.Position - startPointerPosition;
var handDelta = Vector3.Dot(SliderTrackDirection.normalized, delta);
OnPointerDragged(Mathf.Clamp(startSliderValue + handDelta / SliderTrackDirection.magnitude, 0, 1));
// Mark the pointer data as used to prevent other behaviors from handling input events
eventData.Use();
}
}
protected virtual void OnPointerDragged(float newSliderValue)
{
SliderValue = newSliderValue;
}

How to remove white touch dot on Windows 10

I am creating a kiosk–like application for a Windows 10 PC with a touch screen as its only input interface. What I want to remove is the white touch dot that is displayed as a visual touch feedback (mostly together with a circle, which can be turned off).
Does anyone know how to do this?
I have already searched the registry if there was a cursor (*.cur) file which is used but did not find any results. Due to that I guess that the touch feedback is displayed differently.
Just to make sure — I do not want to lose touch functionality, only the visual feedback needs to be gone.
For WPF programs:
In order to remove the touch feedback from WPF elements, it's enough to set Stylus.IsTapFeedbackEnabled dependency property to false. You may want to do that within styles:
<Style x:Key="yourStyle">
<Setter Property="Stylus.IsTapFeedbackEnabled" Value="False" />
</Style>
The white touch dot you cited is actually a cursor. Whenever you touch the screen, Windows replaces the cursor set for the control with the touch cursor. To avoid this honestly ugly behavior, you can set your cursor to Cursors.None, so that the cursor will be hidden. Paste the code below inside your Window and you won't see your white touch dot anymore.
protected override void OnPreviewTouchDown(TouchEventArgs e)
{
base.OnPreviewTouchDown(e);
Cursor = Cursors.None;
}
protected override void OnPreviewTouchMove(TouchEventArgs e)
{
base.OnPreviewTouchMove(e);
Cursor = Cursors.None;
}
protected override void OnGotMouseCapture(MouseEventArgs e)
{
base.OnGotMouseCapture(e);
Cursor = Cursors.Arrow;
}
protected override void OnPreviewMouseMove(MouseEventArgs e)
{
base.OnPreviewMouseMove(e);
if (e.StylusDevice == null)
Cursor = Cursors.Arrow;
}
Your cursor will always be set to Cursors.Arrow when you're using the mouse, though, so you could lose a different cursor you had set to the window. It'd be an easy task to tweak this behavior — my code only serves for demonstration purposes.
For Windows Forms programs:
Looking at the Reference Source for Stylus.IsTapFeedbackEnabled, I've figured out the P/Invoke calls that happen under the hood. Here's what I've come up with for Windows Form applications:
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace TouchableWinform
{
public class TouchableForm : Form
{
private const string TOUCH_SUPPORT_CATEGORY = "Touch support";
private const bool IS_PRESS_AND_HOLD_ENABLED_DEFAULT_VALUE = false;
private const bool IS_FLICKS_ENABLED_DEFAULT_VALUE = false;
private const bool IS_TAP_FEEDBACK_DEFAULT_VALUE = false;
private const bool IS_TOUCH_FEEDBACK_DEFAULT_VALUE = false;
/// <summary>
/// Gets or sets a values indicating whether press and hold is enabled.
/// </summary>
[Category(TOUCH_SUPPORT_CATEGORY), Description("Gets or sets a values indicating whether press and hold is enabled."), EditorBrowsable(EditorBrowsableState.Always), DefaultValue(IS_PRESS_AND_HOLD_ENABLED_DEFAULT_VALUE)]
public bool IsPressAndHoldEnabled
{
get;
set;
} = IS_PRESS_AND_HOLD_ENABLED_DEFAULT_VALUE;
/// <summary>
/// Gets or sets a value indicating whether flicks are enabled.
/// </summary>
[Category(TOUCH_SUPPORT_CATEGORY), Description("Gets or sets a value indicating whether flicks are enabled."), EditorBrowsable(EditorBrowsableState.Always), DefaultValue(IS_FLICKS_ENABLED_DEFAULT_VALUE)]
public bool IsFlicksEnabled
{
get;
set;
} = IS_FLICKS_ENABLED_DEFAULT_VALUE;
/// <summary>
/// Gets or sets whether a value indicating whether tap feedback is enabled.
/// </summary>
[Category(TOUCH_SUPPORT_CATEGORY), Description("Gets or sets whether a value indicating whether tap feedback is enabled."), EditorBrowsable(EditorBrowsableState.Always), DefaultValue(IS_TAP_FEEDBACK_DEFAULT_VALUE)]
public bool IsTapFeedbackEnabled
{
get;
set;
} = IS_TAP_FEEDBACK_DEFAULT_VALUE;
/// <summary>
/// Gets or sets whether a value indicating whether touch feedback is enabled.
/// </summary>
[Category(TOUCH_SUPPORT_CATEGORY), Description("Gets or sets whether a value indicating whether touch feedback is enabled."), EditorBrowsable(EditorBrowsableState.Always), DefaultValue(IS_TOUCH_FEEDBACK_DEFAULT_VALUE)]
public bool IsTouchFeedbackEnabled
{
get;
set;
} = IS_TOUCH_FEEDBACK_DEFAULT_VALUE;
/// <summary>
/// Processes Windows messages.
/// </summary>
/// <param name="m">The Windows <see cref="Message"/> to process.</param>
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x2CB:
m.Result = new IntPtr(1);
break;
case 0x2CC:
uint flags = 0;
if (!IsPressAndHoldEnabled)
flags |= 1;
if (!IsTapFeedbackEnabled)
flags |= 8;
flags |= IsTouchFeedbackEnabled ? (uint)0x100 : 0x200;
if (!IsFlicksEnabled)
flags |= 0x10000;
m.Result = new IntPtr(flags);
break;
default:
base.WndProc(ref m);
break;
}
}
}
}
Unfortunately, for some reason I couldn't still figure out, it doesn't quite look to be working. I'm open to any suggestions.
In Windows 10, you can use pointer messages to handle touches. This would make WPF act like native UWP app behavior. The white dot will disappear and touch move animation get fixed.
If you are using .NET Core, add this line to your App.xaml.cs constructor:
public partial class App : Application
{
public App()
{
AppContext.SetSwitch("Switch.System.Windows.Input.Stylus.EnablePointerSupport", true);
}
}
For .NET Framework, you should add App.config file to project. The contents are shown below:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7" />
</startup>
<runtime>
<AppContextSwitchOverrides value="Switch.System.Windows.Input.Stylus.EnablePointerSupport=true" />
</runtime>
</configuration>
Sources:
How to enable pointer message support in WPF .NET Core
WPF will have a touch offset after trun on the WM_Pointer message

How to catch implicit menu 'Back' command?

I'm programming a J(2)ME app (actually a MIDlet) where more commands than command buttons available are shown on the screen and I'm stuck with this situation:
The mapping to concrete user interface constructs may also depend on
the total number of the commands. For example, if an application asks
for more abstract commands than can be mapped onto the available
physical buttons on a device, then the device may use an alternate
human interface such as a menu. For example, the abstract commands
that cannot be mapped onto physical buttons are placed in a menu and
the label "Menu" is mapped onto one of the programmable buttons.
http://docs.oracle.com/javame/config/cldc/ref-impl/midp2.0/jsr118/javax/microedition/lcdui/Command.html
So in this situation a Menu is auto-generated and a 'Select' and 'Back' choice added. The 'Back' choice is supposed to exit the menu and go back to the previous screen. This works in principle, problem is I need to catch it somehow and trigger a redraw, otherwise the screen goes blank.
So my question is: Is there a way to catch this 'implicit' (automatically added 'Back' command ?
Code example and result:
public class HelloWorld extends MIDlet
{
private Form helloFrm;
private Display display;
public HelloWorld() {
Command command1 = new Command("Cmd 1", Command.SCREEN, 1);
Command command2 = new Command("Cmd 2", Command.SCREEN, 0);
Command command3 = new Command("Cmd 3", Command.SCREEN, 0);
Command command4 = new Command("Cmd 4", Command.SCREEN, 0);
helloFrm = new Form("Hello World");
helloFrm.addCommand(command1);
helloFrm.addCommand(command2);
helloFrm.addCommand(command3);
helloFrm.addCommand(command4);
}
public void startApp()
{
display = Display.getDisplay(this);
display.setCurrent(helloFrm);
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}
edit to add more detail:
As per my comment, I'm going back from a Form to Canvas in my app, that's where the screen blanking happens.
I've already added my own 'Back' command, this one works correctly as I can catch easily with CommandListener and treat accordingly (trigger a redraw). But now I have two 'Back' commands, the implicit one (blanking) and mine.
So the alternative version of the question is: Can I prevent the adding of the implicit 'Back' command somehow ?
You can't prevent the adding of the implicit 'Back' command, but you can redraw the screen from the call to Canvas.showNotify:
The implementation calls showNotify() immediately prior to this Canvas
being made visible on the display. Canvas subclasses may override this
method to perform tasks before being shown, such as setting up
animations, starting timers, etc. The default implementation of this
method in class Canvas is empty.

Resizing GXT Window When Browser Window Resizes

Developing using GXT 2.2.5 on GWT 2.3.0.
The application I'm working on displays a resizable Window with auto scrollbars. I want to make sure the Window size does not exceed the size of the browser window it gets displayed in. To that effect, I added the following code:
addWindowListener(new WindowListener()
{
public void windowActivate(WindowEvent we)
{
super.windowActivate();
Window window = we.getWindow();
window.layout(true);
int width = window.getWidth();
int height = window.getHeight();
int maxWidth = XDOM.getViewportWidth();
int maxHeight = XDOM.getViewportHeight();
window.setSize(Math.min(width, maxWidth), Math.min(height, maxHeight));
window.center();
}
};
This manages sizing the Window to fit in the browser when it gets opened quite nicely.
My problem is that if the user then resizes the browser window, the open Window does not adjust and ends up being clipped.
Is there some way for me to either force the Window to stay within the boundaries of the browser, or capture the resize event so that I can tell the Window to resize accordingly?
Thanks.
You need to add the listener (actually handler -- listeners got depreciated) to the browser window.
So if you have several different windows you show at different times that all need to be resized with the window, you need to have a listener for each window and add it to the browser window when the window is shown.
To add a listener to the browser Window, use:
com.google.gwt.user.client.Window.addResizeHandler(handler);
So for example to resize ContentPanel cp:
com.google.gwt.event.logical.shared.ResizeHandler handler = new ResizeHandler() {
#Override public void onResize(com.google.gwt.event.logical.shared.ResizeEvent event) {
cp.setWidth(event.getWidth());
cp.setHeight(event.getHeight());
}
};
So then if you switch to a new view or ContentPanel you need to register that...
com.google.gwt.user.client.Window.addResizeHandler(handler2);
com.google.gwt.event.logical.shared.ResizeHandler handler2 = new ResizeHandler() {
#Override public void onResize(com.google.gwt.event.logical.shared.ResizeEvent event) {
cp2.setWidth(event.getWidth());
cp2.setHeight(event.getHeight());
}
};
NOTE:
You can't do event.getWindow() for the ResizeEvent you need to handle that another way.
Actually I tend to do it in a constructor like:
com.google.gwt.event.logical.shared.ResizeHandler handler2;
public MyDialog(){
handler2 = new ResizeHandler() {
#Override public void onResize(com.google.gwt.event.logical.shared.ResizeEvent event) {
setWidth(event.getWidth());
setHeight(event.getHeight());
}
};

Why would MonoTouch not garbage collect my custom UIButton unless I call button.RemoveFromSuperview()?

There seems to be something holding a reference to my custom button, MyButton (which inherits from UIButton), causing it not to be garbage collected unless I remove it from the superview. This, in turn, would cause the view controller that it is on to also not be finalized and collected.
In my example, I have my custom button but I also have a standard UIButton on the view controller which does not need to be removed from the superview in order to be collected. What's the difference? Looks pretty similar to me.
See this code. The irrelevant lines were removed for example's sake. Some things to note about the sample:
-MyButton is pretty empty. Just a constructor and nothing else overridden.
-Imagine MyViewController being on a UINavigationController
-LoadView() just creates the buttons, hooks up an event for each and adds it to the view
-Touching _button would push another MyViewController to the nav controller
-I'm doing some reference cleanup when popping view controllers off the nav controller in ViewDidAppear()
-In CleanUpRefs() you'll see that I have to remove _myButton from superview in order for all the objects to be garbage collected. _button, on the other hand does not need to be removed.
-I'm expecting the entire MyViewController to be collected, including all subviews, when popping from the nav controller but commenting out _myButton.RemoveFromSuperview() stops this from happening.
public class MyViewController : UIViewController
{
private UIButton _button;
private MyButton _myButton;
private MyViewController _nextController;
public override void LoadView()
{
base.LoadView();
_button = UIButton.FromType(UIButtonType.RoundedRect);
_button.TouchUpInside += PushNewController;
View.AddSubview(_button);
_myButton = new MyButton();
_myButton.TouchUpInside += MyButtonTouched;
View.AddSubview(_myButton);
}
private void PushNewController(object sender, EventArgs e)
{
_nextController = new MyViewController();
NavigationController.PushViewController(_nextController, true);
}
private void MyButtonTouched(object sender, EventArgs e)
{
Console.WriteLine("MyButton touched");
}
public void CleanUpRefs()
{
//_button.RemoveFromSuperview();
_myButton.RemoveFromSuperview();
// remove reference from hooking up event handler
_button.TouchUpInside -= PushNewController;
_myButton.TouchUpInside -= MyButtonTouched;
_button = null;
_myButton = null;
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if(_nextController != null)
{
_nextController.CleanUpRefs();
_nextController = null;
}
}
}
It seems as if there's something different with the fact that MyButton isn't a straight UIButton in that it is inherited. But then again, why would there be an extra reference count to it that's being removed by calling RemoveFromSuperview() especially when there's a UIButton just like it that doesn't need to be removed?
(I apologize for the really bad layout, stackoverflow seems to have problems laying out bullets right above code snippets)
Update: I filed a bug report with the MonoTouch team. You can download the sample project from there if you want to run it. Bug 92.
The reason for not garbage collecting in that scenario is just a bug in MonoTouch.
The upcoming MonoTouch release will contain a fix for this. If you are in a hurry, you can replace your /Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll with the copy I placed here:
http://tirania.org/tmp/monotouch.dll
I would make a backup, in case I did something wrong in my work-in-progress library.

Resources