Check whether the Control is a Button in c++/cli - c++-cli

How can I check whether the Control^ is a Button^ in the following code?
System::Void DisableControls(Control ^parent)
{
for each (Control^ c in parent->Controls)
{
if(c== /*Check for Button*/)
{
//Do something
}
}
}

You can use GetType() and typeid for this:
if (c->GetType() == Button::typeid) { /* ... */ }

You didn't specify whether you were using WinForms or WPF. The WinForms button, System.Windows.Forms.Button, doesn't have any built-in subclasses, but the WPF button, System.Windows.Controls.Button, does have some subclasses, and if you're using one of those subclasses, you'll miss it if you compare to typeid.
Instead, I'd do a dynamic cast (equivalent to the as keyword in C#), and check for null.
Button b = dynamic_cast<Button^>(c);
if(b != nullptr) { ... }

Related

MRTK and Grip Press

I'm using MRTK 2.3.0 trying to catch a "Grip Press" event from the Mixed Reality motion controller.
I've setup the Input Action in the MRTK Toolkit in the Hierarchy of Unity. I've also assigned the action to the controller's grip button in the Controller Definitions. I'm using the following code and made sure the Grip variable is assigned to the Grip Press event. Nothing happens... I'm able to catch touchpad and joystick, menu button press, but not Grip? Why?
According to this documentation: https://microsoft.github.io/MixedRealityToolkit-Unity/Documentation/MixedRealityConfigurationGuide.html the Grip should be a "float" as it's designed as single axis (I wonder why, since it's a button and not a trigger...). However, I'm trying to catch the event where I can... not working...
Anyone understand what the heck I'm trying to say here? (sorry, the code below also includes other events that I can catch without a hickup).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit;
public class TestInput : MonoBehaviour, IMixedRealityBaseInputHandler,
IMixedRealityInputHandler<Vector2>, IMixedRealityInputHandler
{
public MixedRealityInputAction Trigger, Grip, Scroll, Swipe, Joystick, DPad, TouchPadClicked, TouchPadTouched, MenuPressed;
public MixedRealityInputAction DPadUp, DPadDown, DPadLeft, DPadRight, JoystickUp, JoystickDown, JoystickLeft, JoystickRight;
private bool TouchpadPressed, MenuButtonPressed, GrabPressed, TouchDialogPadPressed, TouchpadClicked, Thouchpadtouched,
ThumbstickActive, ThumbstickPressed, VRManipulationStarted, ScrubStarted, PlayPause = false;
private void OnEnable()
{
IMixedRealityInputSystem inputSystem;
if (MixedRealityServiceRegistry.TryGetService<IMixedRealityInputSystem>(out inputSystem))
{
inputSystem?.RegisterHandler<IMixedRealityBaseInputHandler>(this);
inputSystem?.RegisterHandler<IMixedRealityInputHandler<Vector2>>(this);
inputSystem?.RegisterHandler<IMixedRealityInputHandler>(this);
inputSystem?.RegisterHandler<IMixedRealityInputHandler<float>>(this);
}
}
private void OnDisable()
{
IMixedRealityInputSystem inputSystem;
if (MixedRealityServiceRegistry.TryGetService<IMixedRealityInputSystem>(out inputSystem))
{
inputSystem?.UnregisterHandler<IMixedRealityBaseInputHandler>(this);
inputSystem?.UnregisterHandler<IMixedRealityInputHandler<Vector2>>(this);
inputSystem?.UnregisterHandler<IMixedRealityInputHandler>(this);
inputSystem?.UnregisterHandler<IMixedRealityInputHandler<float>>(this);
}
}
public void OnInputChanged(InputEventData<Vector2> ed)
{
Debug.Log("InputChanged");
if (ed.MixedRealityInputAction == DPad)
{
Debug.Log("Touched Touchpad at:" + ed.InputData.x.ToString() + "," + ed.InputData.y.ToString());
}
if (ed.MixedRealityInputAction == Joystick)
{
Debug.Log("Touched Joystick at:" + ed.InputData.x.ToString() + "," + ed.InputData.y.ToString());
}
}
public void OnInputChanged(InputEventData ed)
{
if (ed.MixedRealityInputAction == MenuPressed)
{
Debug.Log("Menu button pressed");
//ActionText.text = "Grab pressed";
}
}
public void OnInputChanged(InputEventData<float> ed)
{
Debug.Log("Float Changed");
if (ed.MixedRealityInputAction == Grip)
Debug.Log("Grab Pressed");
}
Ok... I got this..... It's a BUG in MRTK.
I have 18 actions defined (when you have DPad left, up, down etc it goes by fast!).
When I try to assign my MixedRealityInputAction to an InputAction in the Inspector, when I try to select GrabPressed (which is the 18th action), I get
IndexOutOfRangeException: Index was outside the bounds of the array.
Microsoft.MixedReality.Toolkit.Input.Editor.InputActionPropertyDrawer.OnGUI
Therefore the action does not work....
I tried to use another InputAction instead and assign it to the grab button (I used Select in this case) and it works like a charm....
Beware....
Try
Input.GetAxisRaw(ControllerMappingLibrary.AXIS_11) > 0 || Input.GetAxisRaw(ControllerMappingLibrary.AXIS_12) > 0;
AXIS_11 is grip press for the left controller while 12 is for the right controller

Monogame 3.5: Mouse Click Not Detected

My monogame game has stopped responding to mouse clicks. Prior to version 3.5, this was working fine. Here's how I'm currently getting the input:
protected override void Update (GameTime game_time)
{
Mouse_Input (game_time);
}
void Mouse_Input(GameTime game_time)
{
mouse_current = Mouse.GetState();
if (mouse_current.LeftButton == ButtonState.Pressed)
{
// click
}
}
Setting breakpoints in the function reveals all the code is being hit, but LeftButton is always ButtonState.Released.
I've tried with both a wired mouse and the trackpad. Keyboard input is working fine. Anyone else running into this?
I always use this way.
MouseState currentMouseState;
MouseState oldMouseState;
public bool checkClick()
{
oldMouseState = currentMouseState;
currentMouseState = Mouse.GetState();
if (Visible)
{
if (currentMouseState.LeftButton == ButtonState.Pressed && oldMouseState.LeftButton == ButtonState.Released)
{
return true;
}
}
}
If you want to check if the Mouse clicks on a Rectangle (Hud elements for example)
public bool checkClickRectangle(Rectangle rec)
{
oldMouseState = currentMouseState;
currentMouseState = Mouse.GetState();
if (Visible)
{
if (rec.Contains(new Vector2(Mouse.GetState().X, Mouse.GetState().Y)) && currentMouseState.LeftButton == ButtonState.Pressed && oldMouseState.LeftButton == ButtonState.Released)
{
return true;
}
}
}
This was actually a not a problem with Monogame, but a problem in my game logic that was very difficult to track down.
After upgrading to 3.5, I had to reconfigure how my Texture2D's were being loaded, which also meant refactoring some classes. I ended up with a class within a class which were both inheriting from Game.
public class Brush_Control : Game
{
public class Tile : Game
{
Process of elimination narrowed the search to this class. I believe this caused an infinite loop that interfered with the input somehow, but without throwing an error or causing an obvious freeze.
Removing the inner Game reference as a parent fixed the problem, and it turns out I no longer need to have it there anyway.

Disable copy/paste on Xamarin forms input field i.e. Entry

I am working on disabling copy/paste option menus on xamarin forms Entry, I am able to disable copy option using IsPassword=true attribute but this attribute also converts the normal input field to password field, which is not a requirement.
<Entry IsPassword="true" Placeholder="Password" TextColor="Green" BackgroundColor="#2c3e50" />
Thanks in advance.
This has to do with how Forms functions. Using iOS as the example here, the CanPerform override referred to in the other answer's Bugzilla issue is using the UIMenuController as the withSender and not the UITextField itself that might otherwise be expected. This is because the EntryRenderer class is a ViewRenderer<TView, TNativeView> type and subsequently is using whatever TNativeView (in this case, the UITextView) has in its CanPerform. Because nothing is going to be overridden by default, one still sees all of the cut/copy/paste options in the UIMenuController.
As a result, there would be a couple options. You could first make the modification where if you don't want copy/paste but are fine with getting rid of everything else, you can use UIMenuController.SharedMenuController.SetMenuVisible(false, false) in a custom renderer inheriting from EntryRenderer. If you look around on SO, there are similar questions where this is a possible route.
Alternatively, you can create a "true" custom renderer inheriting from ViewRenderer<TView, TNativeView> as ViewRenderer<Entry, YourNoCopyPasteUITextFieldClassName>. The class inheriting from UITextField can then override CanPerform as something like follows:
public override bool CanPerform(Selector action, NSObject withSender)
{
if(action.Name == "paste:" || action.Name == "copy:" || action.Name == "cut:")
return false;
return base.CanPerform(action, withSender);
}
This will require more effort because the custom renderer will not have the same behavior as the EntryRenderer, but as Xamarin.Forms is now open source, you could look to it for some ideas as to how the EntryRenderer functions normally. Something similar would likely have to be done for Android.
Edit: For Android, you can probably use this SO answer as a starting point: How to disable copy/paste from/to EditText
Another custom renderer, this time inheriting from ViewRenderer<Entry, EditText>, and create a class inside of it like this (in the most basic form):
class Callback : Java.Lang.Object, ActionMode.ICallback
{
public bool OnActionItemClicked(ActionMode mode, IMenuItem item)
{
return false;
}
public bool OnCreateActionMode(ActionMode mode, IMenu menu)
{
return false;
}
public void OnDestroyActionMode(ActionMode mode)
{
}
public bool OnPrepareActionMode(ActionMode mode, IMenu menu)
{
return false;
}
}
Then, in your OnElementChanged method, you can set the native control and the CustomSelectionActionModeCallback value:
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.CustomSelectionActionModeCallback = new Callback();
}
}
Doing something like the following appears to disable all of the copy/paste/cut functionality on the custom entry as far as the toolbar goes. However, you can still long click to show the paste button, to which I've poked around a bit hadn't found an answer yet beyond setting LongClickable to false. If I do find anything else in that regard, I'd make sure to update this.

TEdit and TCheckBox Validations

My purpose is that the users will never be able to check a TCheckBox when the number is entered into a TEdit less than 7 digits. Also, this TCheckBox can never be checked when the TEdit is being empty.
A problem of my codes is sometimes TCheckBox can still be checked although TEdit is being empty.
Moreover, my another target is that the start button can never be executed or will always display an error message if the start button is clicked when the TCheckBox is checked while the TEdit is being empty.
The problem is what codes should I put in the start button ?.
I am using the following code:
//--------------------------------------------------------------------------------
void __fastcall TForm::MyTEditBoxKeyPress(TObject *Sender, System::WideChar &Key)
{
if( Key == VK_BACK ) return;
if((Key < '1') || (Key > '9'))
{
MessageDlg("Please enter number only.",mtInformation, TMsgDlgButtons()<< mbOK, 0);
Key = 0;
}
}
//--------------------------------------------------------------------------------
void __fastcall TForm::MyTEditBoxExit(TObject *Sender)
{
if (MyTEditBox->Text.Length() < 7) {
MessageDlg("Please enter at least 7 digit.",mtInformation, TMsgDlgButtons()<< mbOK, 0);
}
}
//--------------------------------------------------------------------------------
void __fastcall TForm::MyCheckBoxClick(TObject *Sender)
{
if (MyCheckBox->Tag == 0 ) {
MyCheckBox->Tag = 1;
if (MyTEditBox->Text.Length() >= 7)
MyCheckBox->Checked = true;
IdThrottler->BitsPerSec = StrToInt64(MyTEditBox->Text);
}
else {
MyCheckBox->Tag = 0;
if (MessageDlg("Please enter at least 7 digit.",mtInformation, TMsgDlgButtons()<< mbOK, 0) == mrYes)
MyCheckBox->Checked = false;
}
}
First off, the throttler's BitsPerSec property is an int, not an __int64, so you should be using StrtoInt() instead of StrToInt64().
You are setting the TCheckBox::Enabled property in the TCheckBox::OnClick event, so the user has to actually click on the TCheckBox to make it update itself. If the user only typed in the TEdit and never clicks on the TCheckBox, it will never be updated.
If you don't want the user to click on the TCheckBox at all unless the TEdit text is adequate, you should use the TEdit::OnChange event to set the TCheckBox::Enabled property, and get rid of your TCheckBox::Tag handling altogether:
void __fastcall TMyForm::MyTEditBoxChange(TObject *Sender)
{
MyCheckBox->Enabled = (MyTEditBox->GetTextLen() >= 7);
}
void __fastcall TMyForm::MyCheckBoxClick(TObject *Sender)
{
if (MyCheckBox->Checked)
IdThrottler->BitsPerSec = StrToInt(MyTEditBox->Text);
else
IdThrottler->BitsPerSec = 0;
}
Do note that just because the user can type in more than 6 digits does not mean its Text represents a value int value. In that situation, StrToInt() will raise an exception.
A different way to handle this is to add a TActionList to your Form, create a custom action in it, assign that action to the TCheckBox::Action property, and then use the TAction::OnUpdate event to set the TAction::Enabled property (which will enable/disable the TCheckBox):
void __fastcall TMyForm::MyActionUpdate(TObject *Sender)
{
MyAction1->Enabled = (MyTEditBox->GetTextLen() >= 7);
}
The benefit of this approach is that the TCheckBox::Enabled property will be updated automatically and in real-time without having to manually react to changes in the TEdit at all.
With that said, if you are using a modern version of C++Builder, TEdit has a NumbersOnly property. When set to true, you don't have to filter keystrokes in the TEdit::OnKeyPress event anymore, the OS will prevent the user from typing non-digit characters for you (besides, when you are filtering manually, you are not allowing the user to type in 0 digits, which is wrong).
If you really must allow the user to enter a number via a TEdit, and if the TEdit::NumbersOnly property is not available in your version of C++Builder, you still have a couple of other options (which you should consider anyway, even in modern C++Builder versions):
make the TEdit read-only, attach a TUpDown to it via the TUpDown::Associate property, and assign appropriate TUpDown::Min and TUpDown::Max values as needed. Use the TUpDown::Position property to update the throttler's BitsPerSec property:
void __fastcall TMyForm::MyActionUpdate(TObject *Sender)
{
MyAction1->Enabled = (MyUpDown->Position > 999999);
}
void __fastcall TMyForm::MyUpDownClick(TObject *Sender, TUDBtnType Button)
{
if ((MyCheckBox->Enabled) && (MyCheckBox->Checked))
IdThrottler->BitsPerSec = MyUpDown->Position;
else
IdThrottler->BitsPerSec = 0;
}
Maybe also use a TTrackBar that sets the TUpDown::Value property in larger increments so the user does not have to press the up/down arrows for more than small adjustments:
void __fastcall TMyForm::MyTrackBarChange(TObject *Sender)
{
MyUpDown->Position = MyTrackBar->Position;
MyUpDownClick(NULL, btNext);
}
Don't bother using a TEdit at all. Use a TCSpinEdit or TSpinEdit instead (depending on your version of C++Builder). The user can type in numbers, and it will reject non-numeric input. It provides up/down arrows, like TUpDown, for making small adjustments. And it has a Value property that returns/accepts an int instead of a String, just like the TUpDown::Position property.
void __fastcall TMyForm::MyActionUpdate(TObject *Sender)
{
MyAction1->Enabled = (MySpinEdit->Value > 999999);
}
void __fastcall TMyForm::MySpinEditChange(TObject *Sender)
{
if ((MyCheckBox->Enabled) && (MyCheckBox->Checked))
IdThrottler->BitsPerSec = MySpinEdit->Value;
else
IdThrottler->BitsPerSec = 0;
}
Either way, the user cannot enter non-numeric values at all, and the TCheckBox still auto-disables itself for values that are smaller than your desired threshold.

Activating find/replace for jface TextViewer eclipse worbench action

I have made an eclipse plugin with TextViewer interface for displaying a text document but the standard find/replace stay in gray mode.
I assume you are using the TextViewer in a view rather than an editor. In this case:
Your view in which the TextViewer is used must "adapt" to org.eclipse.jface.text.IFindReplaceTarget i.e. its getAdapter() must return the target from viewer.
You need to explicitly register a handler for "org.eclipse.ui.edit.findReplace" command (which can be org.eclipse.ui.texteditorFindReplaceAction). Check out Platform Command Framework to get started.
I've used Martii Käärik's pointers for finding the answer to this question. I've got it working with the following code, which however uses an internal string identifier from TextEditor. Still, here it goes.
getAdapter() in the view must be implemented like this (viewer is an instance of TextViewer)
public Object getAdapter(Class adapter) {
if (IFindReplaceTarget.class.equals(adapter)) {
if (viewer != null) {
return viewer.getFindReplaceTarget();
}
}
return super.getAdapter(adapter);
}
In createPartControl() of your view, add this code:
FindReplaceAction findAction= new FindReplaceAction(ResourceBundle.getBundle("org.eclipse.ui.texteditor.ConstructedTextEditorMessages"), null, this);
IHandlerService handlerService= (IHandlerService) getSite().getService(IHandlerService.class);
IHandler handler= new AbstractHandler() {
public Object execute(ExecutionEvent event) throws ExecutionException {
if (viewer != null && viewer.getDocument() != null)
findAction.run();
return null;
}
};
handlerService.activateHandler("org.eclipse.ui.edit.findReplace", handler);
No XML required.