I'm actually working on a .Net Treeview-based Interface in 3D Studio Max, therefore coding with maxscript and C#. I've been desperately looking for a way to override the default behavior of a keyboard action, namely selecting the next node starting by the character type in.
For instance, I'd like to call a custom function when pressing the letter "F" and nothing more. By now, it actually run the function but also selects the next node starting with an F. Would anyone know how to prevent this last behavior ?
Thanks a lot.
Have you tried setting the Handled-Property (see HERE) or the SuppressKeyPress-Property (see HERE) of the KeyEventArgs to true?
Related
I have a plugin running inside Maya that needs to perform an 'eye dropper' test against objects in the scene. My Plugin is running as a hosted WPF control, so I have a C# button event callback that wants to operate in a modal fashion until the hit is performed or escape is pressed. This was really easy to do in 3D Studio Max, but I cannot find out how to do this in Maya.
Any advice?
I do miss that in 3dsMax, but as far as I know, no, there's no built-in functionality to do that.
Most tools in Maya work already having a selection before execution so then the tool can use cmds.ls(sl=True) to capture the selection and preform your validation.
What you can do is mimic an object picker by using a selection callback. There's cmds.scriptJob, but it's more efficient to use OpenMaya's callbacks. Here's an example that uses a class to store the callback's id and auto-manages it:
import maya.cmds as cmds
import maya.OpenMaya as OpenMaya
class ObjectPicker():
_id = None # Store callback's id here.
def __init__(self):
# When this class is created, add the callback.
OpenMaya.MGlobal.displayWarning("Please pick an object")
ObjectPicker.add_callback()
#staticmethod
def on_selection_changed(*args):
# This gets triggered from the callback when the user changes the selection.
# Auto-remove the callaback afterwards.
print "Selection:", cmds.ls(sl=True)
ObjectPicker.remove_callback()
#staticmethod
def add_callback():
# First remove any existing callback, then store the id in this class.
ObjectPicker.remove_callback()
ObjectPicker._id = OpenMaya.MEventMessage.addEventCallback("SelectionChanged", ObjectPicker.on_selection_changed)
#staticmethod
def remove_callback():
# Remove the callback so it stops triggering the function.
if ObjectPicker._id is not None:
OpenMaya.MEventMessage.removeCallback(ObjectPicker._id)
ObjectPicker._id = None
# After calling this, pick a new object then it will print it in the Script Editor.
picker = ObjectPicker()
After creating an new instance of the class with picker = ObjectPicker(), a warning will pop-up to the user to pick an object. After the selection changes, it triggers the callback which prints the selection to the Script Editor then removes its own callback.
I think this might work, but Maya isn't 3dsMax, and at the end of the day it might be best to not force one software to work like another. So I'd consider to just stick with what everyone is already used to, and that is to work with the user's current selection.
Edit:
Sorry just noticed c++ tag, but the same concept should apply.
Edit #2:
I just learned about the command cmds.scriptCtx, so a picker does exist! I think it's an older command as it seems to only support MEL and the implementation doesn't feel that great. If you want to learn more then check out my answer to another question.
I apologize in advance... I'm new to C# and am trying to teach myself (badly)!
I've been set a number of tasks to decipher some code and explain what it's doing, but on these three pieces I'm really struggling - I only have the code detailed - nothing else to put it onto context... otherwise I think I'd be fine.
if (HasMark && !MarkReference.Entity.IsValidOn(DateSignedUp.Value)) {
LogError(PersonMessages.MarkNotValidOnDateSignedUp(DateSignedUp));
My thought:
If HasMark variable is true and the DateSignedUp value is false, then call the PersonMessages error and specify the DateSigned up value.
if (From.HasValue && From.Value<Session.Current.VirtualNow) logError(PersonNonMessages.PastHoliday);
My thought: If From is true and From equals (whatever) "Session.Current.VirtualNow" is, through up the PersonNonMessages.PastHoliday error.
if (pastAuditLogs != null) pastAuditLogs.ForEach(x => x.AuditLogs = auditLogs);
My thought: If pastAuditLogs isn't null, for each entry in the pastAuditLog, loop through and find the latest entry for each.
Could anyone please advise on if any of my assumptions above are correct, or if I'm even close to understanding the code?
Apologies it's so vague - if there was any other supporting code or background scenario it'd be 10x easier to understand!
Many thanks
You're using Visual Studio, correct?
You can right click on any symbol (like HasMark) and then choose Show Definition. Then, you can see a white arrow in a blue circle at the upper left of your pane, that takes you back to where you were. This is an incredibly handy feature for code archaelogy.
Also, if you hover your cursor over code you often get a bit of explanation in a tooltop.
Let's tear apart this hunk of code bit by bit...
if (HasMark && !MarkReference.Entity.IsValidOn(DateSignedUp.Value)) {
LogError(PersonMessages.MarkNotValidOnDateSignedUp(DateSignedUp));
}
It means...
If HasMark is true....
Call the boolean-valued function MarkReference.Entity.IsValidOn() ...
Passing the value DateSignedUp.Value
If that function returns false (!) ...
Call the function PersonMessages.MarkNotValidOnDateSignedUp() ...
Passing the value DateSignedUp ...
and pass the returned value to the function LogError().
The && operator won't perform step 2 above if HasMark is false.
The order I've shown here is important. In this bit of code, the second line seems to have the side effect of marking something not valid. But maybe that MarkNotValidOnDateSignedUp() method just looks up some message to toss into LogError().
To know exactly what all this stuff means isn't possible without having your code base present. That's what you use Show Definition to do.
<CTRL><SHIFT><F> activates a Find All function. That's handy too.
Can you run this stuff in the debugger? If so, step through it with Step Into and see what it does.
Pro tip: There's an addon package to Visual Studio called Resharper. It helps with this kind of code archaelogy. They have a free evaluation and sell personal copies for short money.
Working on a text editor here...
I'm trying to figure out if the user has actually caused any changes in a textbox after a keyboard event has occurred. Obviously if they press a standard keys like, A B C, it will fire, but I'm more interested if there's a way, besides enumerating all possible, non-input options.
I will note that I realize the state of the textbox could be compared before and after, but that seems like it would be a poor use of memory, and CPU time if it was a large document. Also, I'm using the Modified property for another purpose, and since it only fires when it changes, that also isn't an options, as it will more often than not be in the true state.
I've though about the enumeration side, but that also seems inefficient, as, I would not only have to ensure that every non-input option is there, but also check for all the exceptions. One example that comes to mind:
If Ctrl is pressed, I don't want to do anything, unless I have Ctrl + V or Ctrl + X.
However, if there's nothing in the clipboard, then Ctrl + V shouldn't do anything, and if nothing is selected, then Ctrl + X shouldn't do anything.
I'm sure there are more exceptions that I'm not thinking of right now.
As for the Modified property, when that changes I'm using it to modify the widow title with/without an asterisk based on it's state. So if I reset the property, it will remove the asterisk.
In the famous method of rubber duck debugging, I ended up solving this simply by asking it. If I've missed a more efficient option, please let me know.
The first and what would seem the be the simpliest option would be to use the TextChanged event, which I actually learned about by adding tags to my post.
If for whatever reason that doesn't work for the future reader, then using the ModifiedChanged event would be the next best option.
Simply put, in my situation, the asterisk only goes away when the document is saved. By setting a flag, I can use an if statement to determine if I need to remove it, and then reset the flag at that point. Something like this:
void saved(){
// ...
saved = true;
}
// ...
if(saved){
removeAsterisk();
saved = false;
}
// ...
Those seem to be the best options, which are neither long in code, nor consuming in time by checking 100k characters.
I'm currently trying to help automate some coded UI tests using C# for a web application. A frequent problem I'm encountering is that it can be extremely difficult to determine if a UITestControl object exists on the page or not. Unfortunately, Microsoft's documentation on their MSDN website for anything regarding coded UI tests is practically non-existant (see here their page for UITestControl).
Basically what I'm asking is:
What is the best way to determine if a UITestControl exists on the page or not?
How does the UITestControl.Exists property work?
What does the UITestControl.Find() method do?
How does the UITestControl.TryFind() method work?
How I've tried to handle it:
As I mentioned earlier, the documentation on all of these classes and methods is mostly blank. The most you can get to describe any of the methods and properties is a 1 line description in Intellisense, so I've been experimenting with the methods that are listed.
First I tried checking if the UITestControl.Exists property was true, but over time and consulting others' experience with it, it became apparent that it always returns true, even if the browser isn't open. Since the option that seemed most obvious wasn't working, I tried using the UITestControl.Find() method, but since it takes no arguments and returns nothing I couldn't figure out what it did. I tried using the UITestControl.TryFind() method, and occasionally it worked, but I found that it only seemed to return false when I wasn't on the correct page; it always returned true otherwise. Clearly I had no idea how it worked, and shouldn't use it as a test.
I figured if I couldn't get the provided methods to do their job, I'd have to try to make my own tools. I most recently tried using Mouse.Hover(UITestControl) in a try/catch block to determine if the control exists like so:
public bool DoesExist(UITestControl control){
if(control == null)
return false;
try{ Mouse.Hover(control); }
catch (UITestException)
{
return false;
}
return true;
}
It works sometimes, but in certain situations it seems to return false positives for reasons I don't understand. I'm still flying blind, and I'm nearly out of ideas.
I am using Visual Studio 2012, and Microsoft .NET Framework version 4.5.50709.
Partial answer about the Find() and TryFind() methods.
After setting the various search properties in the class instance for the control the Find() method does the actual searching for a control to match. The SearchProperties are used to try and find a control. If no controls are found then the search fails - forget exactly what happens then, possibly an exception is thrown but the documentation does not state that. If one control is found that the Find() completes. If two or more are found then the search continues by using FilterProperties to reduce the number of controls found to one.
The Coded UI recorder generates code of the style UIControl aControl = this.UIMap.uione.uitwo.uithree; which leads to the question of how does uione get a value referring to a control such that uitwo can be evauated? The only answer I have found is in the Description part of http://blogs.msdn.com/b/balagans/archive/2009/12/28/9941582.aspx which says "the search for the control starts ( explicit by Find() or implicit by any usage of the control in actions or property validations )".
So Find() performs the search for a control and it can be called explicitly or implicitly.
TryFind() is basically the same as Find() except that it returns a boolean indicating whether the control was found. Again, the documentation is poor but I believe that TryFind() returns true if exactly one control is found, false otherwise.
Another useful find method is FindMatchingControls which returns a (possibly empty) collection of all controls that match the search criteria.
As per yonitdm's answer, using the BoundingRectangle can help when there are multiple items that match but most are not on display. The values of Top and Left can also be used. Doing a FindMatchingControls and screening the results to ignore anything with negative Top or Left may work.
When developing tests the DrawHighlight method is useful, it draws a rectangle around a control. The same sort of rectangle that is drawn when recording assertions with the cross-hairs tool.
The Coded UI content index has lots of good information. The link to "How does UI Test Framework find (search) for a control" may be particularly helpful for you.
Instead of using obj.Exists() we have coded our own exists method that uses a combination approach of EnsureClickable() and BoundingRectangle.Width>0 to make sure that the control has a screen point.
ETA- oops, sorry left off an important part. Updated to add .Width to make sure it's greater than 0, you may need to use length if you width is somehow not working.
I am using tryfind() .. it is working fine.
if (obj_webor.GenLink.TryFind())
{
logdata.WriteLine(obj_webor.GenInnerText + " Exist !");
}
else
{
logdata.WriteLine(obj_webor.GenInnerText + " Does Not Exist");
}
Earlier i was using obj_webor.GenLink.exist().. but is was giving error if it was control not existing and exception occurs. tryfind is ok
When I used to develop in C++, I remember that Visual Studio had an entry in its Autos window whenever returning from a function call. This entry would tell me what value was returned from that function.
One might argue that if a function returns a value, then you should set a variable to that value, i.e.
int i = GetRandomInt();
But as a contrived example, suppose I wanted to do this:
CycleTushKicker( GetRandomInt());
Instead of stepping into CycleTushKicker to figure out how many lickings my kid gets, I'd just like to know the value as soon as I exit GetRandomInt.
Is there a way to get this when using C#?
EDIT -- followed #Michael Goldshetyn's advice and filed a feature suggestion on Microsoft Connect. You can place your votes here: https://connect.microsoft.com/VisualStudio/feedback/details/636130/display-return-value-from-function-in-autos-window-for-c
There is no way to see the return value of a function in the Autos pane of VS2010 when using C#. If you want to be able to see this value, you will need to assign it to a temporary variable, and then you will see this variable's value (at least in debug builds).
Update
VS2013 now offers this functionality
It is better to just use a temporary variable.
This will allow you to see this in the debugging windows, but also allow you to set a break point, and step cleanly over or through each function individually.
By doing the following:
var randomInt = GetRandomInt();
CycleTushKicker(randomInt);
You effectively create exactly the same code, but it is much simpler to debug.