Why not getting `ButtonPressEvent` - c#

I am experimenting a bit with monodevelop/c#/gdk and I was able to create a window with a DrawingArea correctly handling the expose event.
The mouse down events however are not dispatched and I don't understand why. The delegates have been set up in the code autogenerated by the gui designer:
this.da.ExposeEvent += new global::Gtk.ExposeEventHandler (this.OnDAExposeEvent);
this.da.ButtonPressEvent += new global::Gtk.ButtonPressEventHandler (this.OnDAButtonPressEvent);
this.da.MotionNotifyEvent += new global::Gtk.MotionNotifyEventHandler (this.OnDAMotionNotifyEvent);
and this is my initialization code:
public MainWindow () : base (Gtk.WindowType.Toplevel)
{
Build ();
Gdk.Color col = new Gdk.Color();
col.Red = col.Green = col.Blue = 0x8888;
da.ModifyBg(StateType.Normal, col);
var p = "wr/wn/wb/wq/wk/wp/br/bn/bb/bq/bk/bp".Split ('/');
for (int i = 0; i < p.Length; i++) {
pieces[p[i]] = new ImageSurface("/home/agriffini/x/chessboard/i" + p [i] + ".png");
}
da.Events |= (Gdk.EventMask.ButtonPressMask
| Gdk.EventMask.ButtonReleaseMask
| Gdk.EventMask.KeyPressMask
| Gdk.EventMask.PointerMotionMask);
}
however the handler function OnDAButtonPressEvent never gets called (checked by placing a breakpoint there).
What is the part that is missing?

Found the problem by looking at console output.
The issue is that event mask must be set before the widget is realized.
This means that when using monodevelop and the gui designer you must set event handlers using the gui in widget->properties->events because the autogenerated Build method will set the event mask at the proper time before realization.
Setting the event mask in the code before calling Build wouldn't work (widget have not been created yet); setting the mask after that call wouldn't work either (they've been already realized).

Related

Why does this added UI button's event not get called?

In developing a mod for Cities: Skylines, I have run across a problem.
Most of my code, as far as I can tell, works fine - but so far, I haven't got to test it. This is because it should all get called in sequence when a button I have added to the UI gets clicked. The click event on this button is not calling the handler I've assigned to it.
This is where I create the button:
public class LoadingExtension : LoadingExtensionBase
{
public override void OnLevelLoaded(LoadMode mode)
{
Debug.LogDebugMessage("Adding 'Generate City Report' button to UI");
// Get the UIView object. This seems to be the top-level object for most
// of the UI.
var uiView = UIView.GetAView();
// Add a new button to the view.
var button = (UIButton)uiView.AddUIComponent(typeof(UIButton));
// Set the text to show on the button.
button.text = "Generate City Report";
// Set the button dimensions.
button.width = 250;
button.height = 30;
// Style the button to look like a menu button.
button.normalBgSprite = "ButtonMenu";
button.disabledBgSprite = "ButtonMenuDisabled";
button.hoveredBgSprite = "ButtonMenuHovered";
button.focusedBgSprite = "ButtonMenuFocused";
button.pressedBgSprite = "ButtonMenuPressed";
button.textColor = new Color32(255, 255, 255, 255);
button.disabledTextColor = new Color32(7, 7, 7, 255);
button.hoveredTextColor = new Color32(7, 132, 255, 255);
button.focusedTextColor = new Color32(255, 255, 255, 255);
button.pressedTextColor = new Color32(30, 30, 44, 255);
// Enable button sounds.
button.playAudioEvents = true;
// Place the button.
button.transformPosition = new Vector3(-1.0f, 0.97f);
// Respond to button click.
// NOT GETTING CALLED
button.eventClick += ButtonClick;
}
public void ButtonClick(UIComponent component, UIMouseEventParameter eventParam)
{
Debug.LogWarningMessage("HIGH LOGIC: Beginning report generation.");
string now = DateTime.Now.ToFileTime().ToString();
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filename = filepath + "\\CityReport-" + now + ".xlsx";
Output fileCreator = new Output(filename);
fileCreator.GenerateReport();
}
}
According to the documentation I've been following, using
button.eventClick += ButtonClick;
should add ButtonClick as the click handler for the button. However, clicking on the button does nothing. The debug message at the start of the handler (the "HIGH LOGIC" message) doesn't get displayed (note: the earlier debug message about adding the button to the UI does). No error messages are displayed either in the game's debug panel or in VS.
I have also tried using new MouseEventHandler(ButtonClick), since the VS inline documentation tells me that the type of eventClick is MouseEventHandler. This doesn't show any errors in VS or the game, but doesn't work either.
(Note: there is official documentation, but it's next to useless.)
Does anyone here have experience with the C:S API? Why is this event not getting called?
You might try taking a small step back to check if a different UI element works; for example, by following the example for adding a UILabel. Registering a click event handler to this one possibly might work, since there's an actual example to follow; although, the documentation says to place this code inside the Start method. I'm not sure, but maybe the UIButton in your code should be placed in a Start method as well.
As an aside, I stumbled upon this link for debugging. Skylines seems to have its own messaging system for debugging.
Something that I did notice in your code is that the first Debug statement uses a different method than the second Debug statement:
Debug.LogDebugMessage("Adding 'Generate City Report' button to UI");
Debug.LogWarningMessage("HIGH LOGIC: Beginning report generation.");
It might not make any difference, but I would test out that Debug.LogWarningMessage call by moving it where the Debug.LogDebugMessage is to see if it actually works.
According to the extremely terse documentation there's a log file called output_log.txt, perhaps there might be some info contained within this file.
Have you tried:
//button.eventClick += ButtonClick;
button.eventClick += (c,e) => {
Debug.LogWarningMessage("HIGH LOGIC: Beginning report generation.");
string now = DateTime.Now.ToFileTime().ToString();
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filename = filepath + "\\CityReport-" + now + ".xlsx";
Output fileCreator = new Output(filename);
fileCreator.GenerateReport();
};
Also have you tried doing this?:
//var button = (UIButton)uiView.AddUIComponent(typeof(UIButton));
var button = uiView.AddUIComponent(typeof(UIButton)) as UIButton
(Sorry, i can't coment yet)
It looks like your click handler, as such, is OK. Change your ButtonClick method to:
public void ButtonClick(UIComponent component, UIMouseEventParameter eventParam)
{
Debug.LogWarningMessage("HIGH LOGIC: Beginning report generation.");
}
and then check the debug output. If you have a bug after that line, then the debug message may not be visible.

Event handler function isn't firing up for created dynamically checkboxes

First of all, I have to mention that i'm a newbie at c#. I'm developing an windows 8 metro app with xaml and c#.
I created an array of checkboxes dynamically and assigned a pointerpressed event to each of them.
the weird problem is that the pointerpressed event is not firing up the registerd function.
If i create the same checkboxes using design tool(I'm using visual Studio 2012), strangely the function does work this time.
As i don't know the number of checkboxes to be created till runtime, using design tool for handling checkboxes isn't an option.The code i'm running is as below:
CheckBox[] chk=new CheckBox[count];
int x=20; //Width of each checkbox(to be incremented for every iteration)
for( int i = 0; i < count ; i++ )
{
chk[i] = new CheckBox();
chk[i].HorizontalAlignment = HorizontalAlignment.Left;
chk[i].Margin = new Thickness(1100, x, 0, 0);
chk[i].VerticalAlignment = VerticalAlignment.Top;
chk[i].Height = 30;
chk[i].Width = 35;
chk[i].PointerPressed += new PointerEventHandler(chkhandler);
gridit.Children.Add(chk[i]);
x = x + 35;
}
private static void chkhandler(object obj, PointerRoutedEventArgs arg)
{
textblock1.Text="Testing"; //Sample Textblock
}
The checkboxes get checked during runtime but the associated function doesn't work.Thanks in advance
Try;
making the event handler public & non-static,
make sure nobody is eating up the events.
what about this:
chk[i].AddHandler(PointerPressedEvent,
new PointerEventHandler(SomeButton_PointerPressed), true);

Monotouch UICalendar Store Events In Custom DB

I'm using https://github.com/Clancey/UICalendar
I want to store the events that it adds as a row in my custom db table. However, I don't currently see that the UICalendar library actually exposes any events to do this. What is the best way to store events added using UICalendar into a custom db? Or at least get access to the event?
Any help extremely appreciated!
[EDIT]
Looks like I need to use EKEvent to find the currently saved value. How would I get the values from the event currently being triggered to save from my application?
Seems like UICalendar is only visual component. You should to handle store/load event via your own code. For example, via SQLite-net ORM library (http://code.google.com/p/sqlite-net/).
If you want to use UICalendar to show/edit event in systemt calendar, use EKEvent and other EventKit framework classes to reach that information.
I actually imported the UICalendar Project into my project and made the changes to CalendarViews.cs line 258 which is where this fun begins.
Below you can see exactly what I did to intercept the event so that they could associate some custom data that I need to store along with the event for the application. Basically this will intercept the event and present a DVC or DialogViewController to handle some extra user interaction. From here you can save stuff accordingly.
private void portriatNavBar ()
{
// _leftButton = new UIBarButtonItem("Calendars", UIBarButtonItemStyle.Bordered, HandlePreviousDayTouch);
NavigationItem.LeftBarButtonItem = _orgLefButton;
NavigationItem.Title = "Calendar";
_rightButton = new UIBarButtonItem (UIBarButtonSystemItem.Add, delegate {
addController = new EKEventEditViewController ();
// set the addController's event store to the current event store.
addController.EventStore = Util.MyEventStore;
addController.Event = EKEvent.FromStore(Util.MyEventStore);
addController.Event.StartDate = DateTime.Now;
addController.Event.EndDate = DateTime.Now.AddHours(1);
addController.Completed += delegate(object theSender, EKEventEditEventArgs eva) {
switch (eva.Action)
{
case EKEventEditViewAction.Canceled :
case EKEventEditViewAction.Deleted :
case EKEventEditViewAction.Saved:
this.NavigationController.DismissModalViewControllerAnimated(true);
break;
}
};
// Going to create a precursor to actually displaying the creation of a calendar event so we can grab everything correctly
RootElement _ctRoot = new RootElement ("Task Details") {
new Section () {
new RootElement ("Clients") {
AppSpecificNamespace.TaskController.GetClientsForCalendar ()
},
new RootElement ("Task Types") {
AppSpecificNamespace.TaskController.GetTypesForCalendar ()
}
},
new Section () {
new StyledStringElement ("Continue", delegate {
this.NavigationController.PopViewControllerAnimated (true);
this.NavigationController.PresentModalViewController (addController, true);
}) { Alignment = UITextAlignment.Center, TextColor = UIColor.Blue }
}
};
DialogViewController AppSpecificDVC = new DialogViewController (_ctRoot);
this.NavigationController.PushViewController (AppSpecificDVC, true);
//this.NavigationController.PresentViewController (AppSpecificDVC, true, null);
});
NavigationItem.RightBarButtonItem = _rightButton;
}
Hope this helps someone else.

Contacting a dynamically created control

I have created a textBox control on run-time for my winform application. The control appears just find once the form loads up, and works great too. However, I have just run into a problem as I realize I do not know how to write the code to write to a dynamically created control.
Let's assume I have created a button (named "Button1") on design time. In Button1's click event, (Button1_Click), I would like to write the word "Hello" to a textBox control that won't be created until the application is executed. Some code below:
C# Code:
// Create the textBox control
TextBox new_textBox = null;
int x = 10;
int y = 10;
int xWidth = 300;
int yHeight = 200;
new_textBox = new TextBox();
new_textBox.Text = controlText;
new_textBox.Name = "textBox" + controlName;
new_textBox.Size = new System.Drawing.Size(xWidth - 10, yHeight - 10);
new_textBox.Location = new Point(x, y);
new_textBox.BringToFront();
new_textBox.Multiline = true;
new_textBox.BorderStyle = BorderStyle.None;
// Add the textBox control to the form
this.Controls.Add(new_textBox);
The Problem:
From Button1_Click event, I cannot get in contact with a control that has not even been created yet. Thus, Visual Studio will throw an obvious error that the control does not exist (because it doesn't).
So, is there some way to dynamically call a control, and more
specifically, a textBox control?
Thank you for any help on the matter,
Evan
Declare the new_textBox at class scope. Then the compiler can access it. For example:
class MyForm
{
TextBox new_textBox;
void InitializeTextBox()
{
new_textBox = new TextBox();
// initialization code here
// Add it to the form
this.Controls.Add(new_textBox);
}
void Button1_Click(...)
{
new_textBox.Text = "clicked";
}
You can make the new_textBox a class member (member of the form). You can again assign it a value and add to the forms controls later dynamically.
It would be a good practice to check if is null in the buttonClick event, though.

FindName returning null

I'm writing a simple tic tac toe game for school. The assignment is in C++, but the teacher has given me permission to use C# and WPF as a challenge. I've gotten all the game logic finished and the form mostly complete, but I've run into a wall. I'm currently using a Label to indicate who's turn it is, and I want to change it when a player makes a valid move. According to Applications = Code + Markup, I should be able to use the FindName method of the Window class. However, it keeps returning null. Here's the code:
public TicTacToeGame()
{
Title = "TicTacToe";
SizeToContent = SizeToContent.WidthAndHeight;
ResizeMode = ResizeMode.NoResize;
UniformGrid playingField = new UniformGrid();
playingField.Width = 300;
playingField.Height = 300;
playingField.Margin = new Thickness(20);
Label statusDisplay = new Label();
statusDisplay.Content = "X goes first";
statusDisplay.FontSize = 24;
statusDisplay.Name = "StatusDisplay"; // This is the name of the control
statusDisplay.HorizontalAlignment = HorizontalAlignment.Center;
statusDisplay.Margin = new Thickness(20);
StackPanel layout = new StackPanel();
layout.Children.Add(playingField);
layout.Children.Add(statusDisplay);
Content = layout;
for (int i = 0; i < 9; i++)
{
Button currentButton = new Button();
currentButton.Name = "Space" + i.ToString();
currentButton.FontSize = 32;
currentButton.Click += OnPlayLocationClick;
playingField.Children.Add(currentButton);
}
game = new TicTacToe.GameCore();
}
void OnPlayLocationClick(object sender, RoutedEventArgs args)
{
Button clickedButton = args.Source as Button;
int iButtonNumber = Int32.Parse(clickedButton.Name.Substring(5,1));
int iXPosition = iButtonNumber % 3,
iYPosition = iButtonNumber / 3;
if (game.MoveIsValid(iXPosition, iYPosition) &&
game.Status() == TicTacToe.GameCore.GameStatus.StillGoing)
{
clickedButton.Content =
game.getCurrentPlayer() == TicTacToe.GameCore.Player.X ? "X" : "O";
game.MakeMoveAndChangeTurns(iXPosition, iYPosition);
// And this is where I'm getting it so I can use it.
Label statusDisplay = FindName("StatusDisplay") as Label;
statusDisplay.Content = "It is " +
(game.getCurrentPlayer() == TicTacToe.GameCore.Player.X ? "X" : "O") +
"'s turn";
}
}
What's going on here? I'm using the same name in both places, but FindName can't find it. I've tried using Snoop to see the hierarchy, but the form doesn't show up in the list of applications to choose from. I searched on StackOverflow and found I should be able to use VisualTreeHelper class, but I don't understand how to use it.
Any ideas?
FindName operates on the XAML namescope of the calling control. In your case, since the control is created entirely within code, that XAML namescope is empty -- and that's why FindName fails. See this page:
Any additions to the element tree after initial loading and processing must call the appropriate implementation of RegisterName for the class that defines the XAML namescope. Otherwise, the added object cannot be referenced by name through methods such as FindName. Merely setting a Name property (or x:Name Attribute) does not register that name into any XAML namescope.
The easiest way to fix your problem is to store a reference to your StatusDisplay label in the class as a private member. Or, if you want to learn how to use the VisualTreeHelper class, there's a code snippet at the bottom of this page that walks the visual tree to find the matching element.
(Edited: Of course, it's less work to call RegisterName than to use the VisualTreeHelper, if you don't want to store a reference to the label.)
I'd recommend reading the first link in its entirety if you plan on using WPF/Silverlight in any depth. Useful information to have.
You have to create a new NameScope for your window:
NameScope.SetNameScope(this, new NameScope());
Then you register name of your label with the window:
RegisterName(statusDisplay.Name, statusDisplay);
So this seems to be all you need to do to make FindName() work.

Categories

Resources